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
d7203748
Commit
d7203748
authored
Feb 15, 2004
by
Steve French
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linux.bkbits.net/linux-2.5
into hostme.bitkeeper.com:/repos/c/cifs/linux-2.5cifs
parents
d5c7cd85
a60e227b
Changes
31
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
850 additions
and
649 deletions
+850
-649
Documentation/DocBook/kernel-locking.tmpl
Documentation/DocBook/kernel-locking.tmpl
+0
-21
Makefile
Makefile
+1
-1
arch/arm/common/amba.c
arch/arm/common/amba.c
+1
-1
arch/arm/kernel/time.c
arch/arm/kernel/time.c
+1
-1
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/generic.c
+5
-0
arch/arm/mm/Kconfig
arch/arm/mm/Kconfig
+2
-2
arch/ia64/kernel/acpi.c
arch/ia64/kernel/acpi.c
+1
-1
arch/ia64/kernel/irq.c
arch/ia64/kernel/irq.c
+0
-2
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca.c
+5
-32
arch/ia64/kernel/smp.c
arch/ia64/kernel/smp.c
+0
-4
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/smpboot.c
+0
-5
arch/ia64/scripts/toolchain-flags
arch/ia64/scripts/toolchain-flags
+15
-0
arch/ia64/sn/kernel/setup.c
arch/ia64/sn/kernel/setup.c
+2
-0
arch/ia64/sn/kernel/sn2/cache.c
arch/ia64/sn/kernel/sn2/cache.c
+1
-1
drivers/char/sn_serial.c
drivers/char/sn_serial.c
+1
-1
drivers/macintosh/via-pmu.c
drivers/macintosh/via-pmu.c
+0
-51
drivers/video/aty/aty128fb.c
drivers/video/aty/aty128fb.c
+568
-457
drivers/video/aty/radeon_accel.c
drivers/video/aty/radeon_accel.c
+4
-4
drivers/video/aty/radeon_base.c
drivers/video/aty/radeon_base.c
+3
-2
drivers/video/cfbcopyarea.c
drivers/video/cfbcopyarea.c
+3
-0
drivers/video/cfbfillrect.c
drivers/video/cfbfillrect.c
+3
-0
drivers/video/cfbimgblt.c
drivers/video/cfbimgblt.c
+3
-0
drivers/video/console/fbcon.c
drivers/video/console/fbcon.c
+64
-11
drivers/video/fbmem.c
drivers/video/fbmem.c
+87
-21
drivers/video/riva/fbdev.c
drivers/video/riva/fbdev.c
+2
-1
drivers/video/softcursor.c
drivers/video/softcursor.c
+3
-2
include/asm-ia64/mca.h
include/asm-ia64/mca.h
+0
-1
include/linux/fb.h
include/linux/fb.h
+21
-2
include/linux/pci_ids.h
include/linux/pci_ids.h
+24
-15
include/video/aty128.h
include/video/aty128.h
+3
-0
net/bluetooth/rfcomm/tty.c
net/bluetooth/rfcomm/tty.c
+27
-10
No files found.
Documentation/DocBook/kernel-locking.tmpl
View file @
d7203748
...
...
@@ -1444,27 +1444,6 @@ as Alan Cox says, <quote>Lock data, not code</quote>.
</para>
</sect1>
<sect1 id="sparc">
<title>The Fucked Up Sparc</title>
<para>
Alan Cox says <quote>the irq disable/enable is in the register
window on a sparc</quote>. Andi Kleen says <quote>when you do
restore_flags in a different function you mess up all the
register windows</quote>.
</para>
<para>
So never pass the flags word set by
<function>spin_lock_irqsave()</function> and brethren to another
function (unless it's declared <type>inline</type>). Usually no-one
does this, but now you've been warned. Dave Miller can never do
anything in a straightforward manner (I can say that, because I have
pictures of him and a certain PowerPC maintainer in a compromising
position).
</para>
</sect1>
</chapter>
<chapter id="Efficiency">
...
...
Makefile
View file @
d7203748
VERSION
=
2
PATCHLEVEL
=
6
SUBLEVEL
=
3
EXTRAVERSION
=
-rc
2
EXTRAVERSION
=
-rc
3
NAME
=
Feisty Dunnart
# *DOCUMENTATION*
...
...
arch/arm/common/amba.c
View file @
d7203748
...
...
@@ -50,7 +50,7 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf,
if
(
nr_env
<
2
)
return
-
ENOMEM
;
snprintf
(
buf
,
bufsz
,
"AMBA_ID=%08
l
x"
,
pcdev
->
periphid
);
snprintf
(
buf
,
bufsz
,
"AMBA_ID=%08x"
,
pcdev
->
periphid
);
*
envp
++
=
buf
;
*
envp
++
=
NULL
;
return
0
;
...
...
arch/arm/kernel/time.c
View file @
d7203748
...
...
@@ -116,7 +116,7 @@ static inline void do_set_rtc(void)
return
;
if
(
next_rtc_update
&&
time_before
(
xtime
.
tv_sec
,
next_rtc_update
))
time_before
(
(
unsigned
long
)
xtime
.
tv_sec
,
next_rtc_update
))
return
;
if
(
xtime
.
tv_nsec
<
500000000
-
((
unsigned
)
tick_nsec
>>
1
)
&&
...
...
arch/arm/mach-sa1100/generic.c
View file @
d7203748
...
...
@@ -159,9 +159,14 @@ static struct resource sa11x0mcp_resources[] = {
},
};
static
u64
sa11x0mcp_dma_mask
=
0xffffffffUL
;
static
struct
platform_device
sa11x0mcp_device
=
{
.
name
=
"sa11x0-mcp"
,
.
id
=
0
,
.
dev
=
{
.
dma_mask
=
&
sa11x0mcp_dma_mask
,
},
.
num_resources
=
ARRAY_SIZE
(
sa11x0mcp_resources
),
.
resource
=
sa11x0mcp_resources
,
};
...
...
arch/arm/mm/Kconfig
View file @
d7203748
...
...
@@ -291,8 +291,8 @@ config ARM_THUMB
depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE
default y
help
Say Y if you want to
have kernel support for ARM Thumb instructions,
fault handlers, and system call
s.
Say Y if you want to
include kernel support for running user space
Thumb binarie
s.
The Thumb instruction set is a compressed form of the standard ARM
instruction set resulting in smaller binaries at the expense of
...
...
arch/ia64/kernel/acpi.c
View file @
d7203748
...
...
@@ -589,7 +589,7 @@ acpi_boot_init (void)
smp_boot_data
.
cpu_count
=
available_cpus
;
smp_build_cpu_map
();
# ifdef CONFIG_NUMA
# ifdef CONFIG_
ACPI_
NUMA
if
(
srat_num_cpus
==
0
)
{
int
cpu
,
i
=
1
;
for
(
cpu
=
0
;
cpu
<
smp_boot_data
.
cpu_count
;
cpu
++
)
...
...
arch/ia64/kernel/irq.c
View file @
d7203748
...
...
@@ -465,8 +465,6 @@ unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs)
desc
->
handler
->
ack
(
irq
);
action_ret
=
handle_IRQ_event
(
irq
,
regs
,
desc
->
action
);
desc
->
handler
->
end
(
irq
);
if
(
!
noirqdebug
)
note_interrupt
(
irq
,
desc
,
action_ret
);
}
else
{
spin_lock
(
&
desc
->
lock
);
desc
->
handler
->
ack
(
irq
);
...
...
arch/ia64/kernel/mca.c
View file @
d7203748
...
...
@@ -239,10 +239,9 @@ ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe)
* and wakes up any processes waiting for error records.
*
* Inputs : sal_info_type (Type of error record MCA/CMC/CPE/INIT)
* called_from_init (1 for boot processing)
*/
static
void
ia64_mca_log_sal_error_record
(
int
sal_info_type
,
int
called_from_init
)
ia64_mca_log_sal_error_record
(
int
sal_info_type
)
{
u8
*
buffer
;
u64
size
;
...
...
@@ -255,7 +254,7 @@ ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init)
salinfo_log_wakeup
(
sal_info_type
,
buffer
,
size
,
irq_safe
);
if
(
irq_safe
||
called_from_init
)
if
(
irq_safe
)
printk
(
KERN_INFO
"CPU %d: SAL log contains %s error record
\n
"
,
smp_processor_id
(),
sal_info_type
<
ARRAY_SIZE
(
rec_name
)
?
rec_name
[
sal_info_type
]
:
"UNKNOWN"
);
...
...
@@ -280,7 +279,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
local_irq_enable
();
/* Get the CMC error record and log it */
ia64_mca_log_sal_error_record
(
SAL_INFO_TYPE_CPE
,
0
);
ia64_mca_log_sal_error_record
(
SAL_INFO_TYPE_CPE
);
return
IRQ_HANDLED
;
}
...
...
@@ -469,32 +468,6 @@ init_handler_platform (pal_min_state_area_t *ms,
while
(
1
);
/* hang city if no debugger */
}
/*
* ia64_mca_check_errors
*
* External entry to check for error records which may have been posted by SAL
* for a prior failure which resulted in a machine shutdown before an the
* error could be logged. This function must be called after the filesystem
* is initialized.
*
* Inputs : None
*
* Outputs : None
*/
int
ia64_mca_check_errors
(
void
)
{
/*
* If there is an MCA error record pending, get it and log it.
*/
printk
(
KERN_INFO
"CPU %d: checking for saved MCA error records
\n
"
,
smp_processor_id
());
ia64_mca_log_sal_error_record
(
SAL_INFO_TYPE_MCA
,
1
);
return
0
;
}
device_initcall
(
ia64_mca_check_errors
);
#ifdef CONFIG_ACPI
/*
* ia64_mca_register_cpev
...
...
@@ -831,7 +804,7 @@ ia64_mca_ucmc_handler(void)
int
recover
=
psp
->
tc
&&
!
(
psp
->
cc
||
psp
->
bc
||
psp
->
rc
||
psp
->
uc
);
/* Get the MCA error record and log it */
ia64_mca_log_sal_error_record
(
SAL_INFO_TYPE_MCA
,
0
);
ia64_mca_log_sal_error_record
(
SAL_INFO_TYPE_MCA
);
/*
* Wakeup all the processors which are spinning in the rendezvous
...
...
@@ -875,7 +848,7 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
local_irq_enable
();
/* Get the CMC error record and log it */
ia64_mca_log_sal_error_record
(
SAL_INFO_TYPE_CMC
,
0
);
ia64_mca_log_sal_error_record
(
SAL_INFO_TYPE_CMC
);
spin_lock
(
&
cmc_history_lock
);
if
(
!
cmc_polling_enabled
)
{
...
...
arch/ia64/kernel/smp.c
View file @
d7203748
...
...
@@ -18,10 +18,6 @@
* 10/13/00 Goutham Rao <goutham.rao@intel.com> Updated smp_call_function and
* smp_call_function_single to resend IPI on timeouts
*/
#define __KERNEL_SYSCALLS__
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
...
...
arch/ia64/kernel/smpboot.c
View file @
d7203748
...
...
@@ -10,10 +10,6 @@
* smp_boot_cpus()/smp_commence() is replaced by
* smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
*/
#define __KERNEL_SYSCALLS__
#include <linux/config.h>
#include <linux/module.h>
...
...
@@ -306,7 +302,6 @@ smp_callin (void)
#ifdef CONFIG_IA64_MCA
ia64_mca_cmc_vector_setup
();
/* Setup vector on AP & enable */
ia64_mca_check_errors
();
/* For post-failure MCA error logging */
#endif
#ifdef CONFIG_PERFMON
...
...
arch/ia64/scripts/toolchain-flags
View file @
d7203748
...
...
@@ -5,9 +5,14 @@
CPPFLAGS
=
""
CC
=
$1
OBJDUMP
=
$2
READELF
=
$3
dir
=
$(
dirname
$0
)
tmp
=
${
TMPDIR
:-
/tmp
}
out
=
$tmp
/out
$$
# Check whether cross-segment segment-relative relocs work fine. We need
# that for building the gate DSO:
$CC
-nostdlib
-static
-Wl
,-T
$dir
/check-segrel.lds
$dir
/check-segrel.S
-o
$out
res
=
$(
$OBJDUMP
--full
--section
.rodata
$out
| fgrep 000 |
cut
-f3
-d
' '
)
rm
-f
$out
...
...
@@ -20,6 +25,16 @@ warning: your linker cannot handle cross-segment segment-relative relocations.
EOF
fi
# Check whether .align inside a function works as expected.
$CC
-c
$dir
/check-text-align.S
-o
$out
$READELF
-u
$out
| fgrep
-q
'prologue(rlen=12)'
res
=
$?
rm
-f
$out
if
[
$res
-eq
0
]
;
then
CPPFLAGS
=
"
$CPPFLAGS
-DHAVE_WORKING_TEXT_ALIGN"
fi
if
!
$CC
-c
$dir
/check-model.c
-o
$out
2>&1 |
grep
__model__ |
grep
-q
attrib
then
CPPFLAGS
=
"
$CPPFLAGS
-DHAVE_MODEL_SMALL_ATTRIBUTE"
...
...
arch/ia64/sn/kernel/setup.c
View file @
d7203748
...
...
@@ -71,6 +71,8 @@ u64 sn_partition_serial_number;
short
physical_node_map
[
MAX_PHYSNODE_ID
];
EXPORT_SYMBOL
(
physical_node_map
);
int
numionodes
;
/*
* This is the address of the RRegs in the HSpace of the global
...
...
arch/ia64/sn/kernel/sn2/cache.c
View file @
d7203748
...
...
@@ -6,7 +6,7 @@
* Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
*
*/
#include <linux/module.h>
#include <asm/pgalloc.h>
/**
...
...
drivers/char/sn_serial.c
View file @
d7203748
...
...
@@ -772,7 +772,7 @@ sn_sal_read_proc(char *page, char **start, off_t off, int count,
int
len
=
0
;
off_t
begin
=
0
;
len
+=
sprintf
(
page
,
"sn_serial: nasid:%d irq:%d tx:%d rx:%d
\n
"
,
len
+=
sprintf
(
page
,
"sn_serial: nasid:%
l
d irq:%d tx:%d rx:%d
\n
"
,
ia64_sn_get_console_nasid
(),
sn_sal_irq
,
sn_total_tx_count
,
sn_total_rx_count
);
*
eof
=
1
;
...
...
drivers/macintosh/via-pmu.c
View file @
d7203748
...
...
@@ -72,13 +72,6 @@
/* How many iterations between battery polls */
#define BATTERY_POLLING_COUNT 2
/* Some debugging tools */
#ifdef CONFIG_XMON
//#define LIVE_DEBUG(req) ((req) && (req)->data[0] == 0x7d)
#define LIVE_DEBUG(req) (0)
static
int
whacky_debug
;
#endif
/* CONFIG_XMON */
static
volatile
unsigned
char
*
via
;
/* VIA registers - spaced 0x200 bytes apart */
...
...
@@ -1218,12 +1211,6 @@ pmu_start(void)
wait_for_ack
();
/* set the shift register to shift out and send a byte */
send_byte
(
req
->
data
[
0
]);
#ifdef CONFIG_XMON
if
(
LIVE_DEBUG
(
req
))
xmon_printf
(
"R"
);
else
whacky_debug
=
0
;
#endif
/* CONFIG_XMON */
}
void
__openfirmware
...
...
@@ -1476,29 +1463,17 @@ pmu_sr_intr(struct pt_regs *regs)
case
sending
:
req
=
current_req
;
if
(
data_len
<
0
)
{
#ifdef CONFIG_XMON
if
(
LIVE_DEBUG
(
req
))
xmon_printf
(
"s"
);
#endif
/* CONFIG_XMON */
data_len
=
req
->
nbytes
-
1
;
send_byte
(
data_len
);
break
;
}
if
(
data_index
<=
data_len
)
{
#ifdef CONFIG_XMON
if
(
LIVE_DEBUG
(
req
))
xmon_printf
(
"S"
);
#endif
/* CONFIG_XMON */
send_byte
(
req
->
data
[
data_index
++
]);
break
;
}
req
->
sent
=
1
;
data_len
=
pmu_data_len
[
req
->
data
[
0
]][
1
];
if
(
data_len
==
0
)
{
#ifdef CONFIG_XMON
if
(
LIVE_DEBUG
(
req
))
xmon_printf
(
"D"
);
#endif
/* CONFIG_XMON */
pmu_state
=
idle
;
current_req
=
req
->
next
;
if
(
req
->
reply_expected
)
...
...
@@ -1506,10 +1481,6 @@ pmu_sr_intr(struct pt_regs *regs)
else
return
req
;
}
else
{
#ifdef CONFIG_XMON
if
(
LIVE_DEBUG
(
req
))
xmon_printf
(
"-"
);
#endif
/* CONFIG_XMON */
pmu_state
=
reading
;
data_index
=
0
;
reply_ptr
=
req
->
reply
+
req
->
reply_len
;
...
...
@@ -1532,18 +1503,10 @@ pmu_sr_intr(struct pt_regs *regs)
case
reading
:
case
reading_intr
:
if
(
data_len
==
-
1
)
{
#ifdef CONFIG_XMON
if
(
LIVE_DEBUG
(
current_req
))
xmon_printf
(
"r"
);
#endif
/* CONFIG_XMON */
data_len
=
bite
;
if
(
bite
>
32
)
printk
(
KERN_ERR
"PMU: bad reply len %d
\n
"
,
bite
);
}
else
if
(
data_index
<
32
)
{
#ifdef CONFIG_XMON
if
(
LIVE_DEBUG
(
current_req
))
xmon_printf
(
"R"
);
#endif
/* CONFIG_XMON */
reply_ptr
[
data_index
++
]
=
bite
;
}
if
(
data_index
<
data_len
)
{
...
...
@@ -1551,12 +1514,6 @@ pmu_sr_intr(struct pt_regs *regs)
break
;
}
#ifdef CONFIG_XMON
if
(
LIVE_DEBUG
(
current_req
))
{
whacky_debug
=
1
;
xmon_printf
(
"D"
);
}
#endif
/* CONFIG_XMON */
if
(
pmu_state
==
reading_intr
)
{
pmu_state
=
idle
;
int_data_state
[
int_data_last
]
=
int_data_ready
;
...
...
@@ -1603,10 +1560,6 @@ via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
intr
=
in_8
(
&
via
[
IFR
])
&
(
SR_INT
|
CB1_INT
);
if
(
intr
==
0
)
break
;
#ifdef CONFIG_XMON
if
(
whacky_debug
)
xmon_printf
(
"|%02x|"
,
intr
);
#endif
/* CONFIG_XMON */
handled
=
1
;
if
(
++
nloop
>
1000
)
{
printk
(
KERN_DEBUG
"PMU: stuck in intr loop, "
...
...
@@ -1629,10 +1582,6 @@ via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
recheck:
if
(
pmu_state
==
idle
)
{
if
(
adb_int_pending
)
{
#ifdef CONFIG_XMON
if
(
whacky_debug
)
xmon_printf
(
"!A!"
);
#endif
/* CONFIG_XMON */
if
(
int_data_state
[
0
]
==
int_data_empty
)
int_data_last
=
0
;
else
if
(
int_data_state
[
1
]
==
int_data_empty
)
...
...
drivers/video/aty/aty128fb.c
View file @
d7203748
...
...
@@ -13,6 +13,7 @@
*
* Benjamin Herrenschmidt
* - pmac-specific PM stuff
* - various fixes & cleanups
*
* Andreas Hundt <andi@convergence.de>
* - FB_ACTIVATE fixes
...
...
@@ -24,6 +25,10 @@
* Paul Mundt
* - PCI hotplug
*
* Jon Smirl <jonsmirl@yahoo.com>
* - PCI ID update
* - replace ROM BIOS search
*
* Based off of Geert's atyfb.c and vfb.c.
*
* TODO:
...
...
@@ -43,6 +48,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
...
...
@@ -57,6 +63,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/console.h>
#include <asm/io.h>
#ifdef CONFIG_PPC_PMAC
...
...
@@ -65,11 +72,6 @@
#include "../macmodes.h"
#endif
#ifdef CONFIG_ADB_PMU
#include <linux/adb.h>
#include <linux/pmu.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
#endif
...
...
@@ -136,8 +138,25 @@ static struct fb_videomode defaultmode __initdata = {
/* Chip generations */
enum
{
rage_128
,
rage_128_pci
,
rage_128_pro
,
rage_M3
rage_128_pro_pci
,
rage_M3
,
rage_M3_pci
,
rage_M4
,
rage_128_ultra
,
};
/* Must match above enum */
static
const
char
*
r128_family
[]
__devinitdata
=
{
"AGP"
,
"PCI"
,
"PRO AGP"
,
"PRO PCI"
,
"M3 AGP"
,
"M3 PCI"
,
"M4 AGP"
,
"Ultra AGP"
,
};
/*
...
...
@@ -146,35 +165,105 @@ enum {
static
int
aty128_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
);
static
void
aty128_remove
(
struct
pci_dev
*
pdev
);
static
int
aty128_pci_suspend
(
struct
pci_dev
*
pdev
,
u32
state
);
static
int
aty128_pci_resume
(
struct
pci_dev
*
pdev
);
/* supported Rage128 chipsets */
static
struct
pci_device_id
aty128_pci_tbl
[]
=
{
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RF
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RI
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RK
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RL
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_Rage128_PD
,
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_LE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_M3_pci
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_LF
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_M3
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_MF
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_M4
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_ML
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_M4
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PA
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PB
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PC
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PD
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro_pci
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PF
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PR
,
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PG
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PH
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PI
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PJ
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PK
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PL
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PM
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PN
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PO
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PP
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro_pci
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PQ
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PR
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro_pci
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PS
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_
U3
,
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_
PT
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_
U1
,
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_
PU
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_LE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_M3
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_LF
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_M3
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PV
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PW
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_PX
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pro
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pci
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RF
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RG
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RK
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pci
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_RL
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_SE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_SF
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_pci
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_SG
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_SH
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_SK
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_SL
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_SM
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_SN
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_TF
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_ultra
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_TL
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_ultra
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_TR
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_ultra
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_TS
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_ultra
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_TT
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_ultra
},
{
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_RAGE128_TU
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
rage_128_ultra
},
{
0
,
}
};
...
...
@@ -185,6 +274,8 @@ static struct pci_driver aty128fb_driver = {
.
id_table
=
aty128_pci_tbl
,
.
probe
=
aty128_probe
,
.
remove
=
__devexit_p
(
aty128_remove
),
.
suspend
=
aty128_pci_suspend
,
.
resume
=
aty128_pci_resume
,
};
/* packed BIOS settings */
...
...
@@ -250,13 +341,6 @@ static struct fb_fix_screeninfo aty128fb_fix __initdata = {
.
accel
=
FB_ACCEL_ATI_RAGE128
,
};
#ifdef MODULE
static
char
*
mode
__initdata
=
NULL
;
#ifdef CONFIG_MTRR
static
int
nomtrr
__initdata
=
0
;
#endif
/* CONFIG_MTRR */
#endif
/* MODULE */
static
char
*
mode_option
__initdata
=
NULL
;
#ifdef CONFIG_PPC_PMAC
...
...
@@ -275,7 +359,7 @@ static int mtrr = 1;
/* PLL constants */
struct
aty128_constants
{
u32
dotcloc
k
;
u32
ref_cl
k
;
u32
ppll_min
;
u32
ppll_max
;
u32
ref_divider
;
...
...
@@ -322,26 +406,20 @@ struct aty128fb_par {
#endif
int
blitter_may_be_busy
;
int
fifo_slots
;
/* free slots in FIFO (64 max) */
#ifdef CONFIG_PMAC_PBOOK
unsigned
char
*
save_framebuffer
;
int
pm_reg
;
int
crt_on
,
lcd_on
;
struct
pci_dev
*
pdev
;
struct
fb_info
*
next
;
#endif
int
asleep
;
int
lock_blank
;
u8
red
[
32
];
/* see aty128fb_setcolreg */
u8
green
[
64
];
u8
blue
[
32
];
u32
pseudo_palette
[
16
];
/* used for TRUECOLOR */
};
#ifdef CONFIG_PMAC_PBOOK
int
aty128_sleep_notify
(
struct
pmu_sleep_notifier
*
self
,
int
when
);
static
struct
pmu_sleep_notifier
aty128_sleep_notifier
=
{
aty128_sleep_notify
,
SLEEP_LEVEL_VIDEO
,
};
static
struct
fb_info
*
aty128_fb
=
NULL
;
#endif
#define round_div(n, d) ((n+(d/2))/d)
...
...
@@ -349,7 +427,6 @@ static struct fb_info *aty128_fb = NULL;
* Interface used by the world
*/
int
aty128fb_init
(
void
);
int
aty128fb_setup
(
char
*
options
);
static
int
aty128fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
);
...
...
@@ -371,10 +448,10 @@ static int aty128_encode_var(struct fb_var_screeninfo *var,
const
struct
aty128fb_par
*
par
);
static
int
aty128_decode_var
(
struct
fb_var_screeninfo
*
var
,
struct
aty128fb_par
*
par
);
#if
!defined(CONFIG_PPC) && !defined(__sparc__)
#if
0
static void __init aty128_get_pllinfo(struct aty128fb_par *par,
void *bios);
static
void
__init
*
aty128_map_ROM
(
struct
pci_dev
*
pdev
);
static void __init *aty128_map_ROM(struct pci_dev *pdev
, const struct aty128fb_par *par
);
static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom);
#endif
static
void
aty128_timings
(
struct
aty128fb_par
*
par
);
...
...
@@ -386,6 +463,15 @@ static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
static
void
wait_for_idle
(
struct
aty128fb_par
*
par
);
static
u32
depth_to_dst
(
u32
depth
);
#define BIOS_IN8(v) (readb(bios + (v)))
#define BIOS_IN16(v) (readb(bios + (v)) | \
(readb(bios + (v) + 1) << 8))
#define BIOS_IN32(v) (readb(bios + (v)) | \
(readb(bios + (v) + 1) << 8) | \
(readb(bios + (v) + 2) << 16) | \
(readb(bios + (v) + 3) << 24))
static
struct
fb_ops
aty128fb_ops
=
{
.
owner
=
THIS_MODULE
,
.
fb_check_var
=
aty128fb_check_var
,
...
...
@@ -395,15 +481,9 @@ static struct fb_ops aty128fb_ops = {
.
fb_blank
=
aty128fb_blank
,
.
fb_ioctl
=
aty128fb_ioctl
,
.
fb_sync
=
aty128fb_sync
,
#if 0
.fb_fillrect = aty128fb_fillrect,
.fb_copyarea = aty128fb_copyarea,
.fb_imageblit = aty128fb_imageblit,
#else
.
fb_fillrect
=
cfb_fillrect
,
.
fb_copyarea
=
cfb_copyarea
,
.
fb_imageblit
=
cfb_imageblit
,
#endif
.
fb_cursor
=
soft_cursor
,
};
...
...
@@ -422,40 +502,26 @@ static struct backlight_controller aty128_backlight_controller = {
* - endian conversions may possibly be avoided by
* using the other register aperture. TODO.
*/
static
inline
u32
_aty_ld_le32
(
volatile
unsigned
int
regindex
,
const
struct
aty128fb_par
*
par
)
static
inline
u32
_aty_ld_le32
(
volatile
unsigned
int
regindex
,
const
struct
aty128fb_par
*
par
)
{
u32
val
;
#if defined(__powerpc__)
asm
(
"lwbrx %0,%1,%2;eieio"
:
"=r"
(
val
)
:
"b"
(
regindex
),
"r"
(
par
->
regbase
));
#else
val
=
readl
(
par
->
regbase
+
regindex
);
#endif
return
val
;
return
readl
(
par
->
regbase
+
regindex
);
}
static
inline
void
_aty_st_le32
(
volatile
unsigned
int
regindex
,
u32
val
,
const
struct
aty128fb_par
*
par
)
static
inline
void
_aty_st_le32
(
volatile
unsigned
int
regindex
,
u32
val
,
const
struct
aty128fb_par
*
par
)
{
#if defined(__powerpc__)
asm
(
"stwbrx %0,%1,%2;eieio"
:
:
"r"
(
val
),
"b"
(
regindex
),
"r"
(
par
->
regbase
)
:
"memory"
);
#else
writel
(
val
,
par
->
regbase
+
regindex
);
#endif
}
static
inline
u8
_aty_ld_8
(
unsigned
int
regindex
,
const
struct
aty128fb_par
*
par
)
static
inline
u8
_aty_ld_8
(
unsigned
int
regindex
,
const
struct
aty128fb_par
*
par
)
{
return
readb
(
par
->
regbase
+
regindex
);
}
static
inline
void
_aty_st_8
(
unsigned
int
regindex
,
u8
val
,
const
struct
aty128fb_par
*
par
)
static
inline
void
_aty_st_8
(
unsigned
int
regindex
,
u8
val
,
const
struct
aty128fb_par
*
par
)
{
writeb
(
val
,
par
->
regbase
+
regindex
);
}
...
...
@@ -473,17 +539,15 @@ _aty_st_8(unsigned int regindex, u8 val, const struct aty128fb_par *par)
#define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val, par)
static
u32
_aty_ld_pll
(
unsigned
int
pll_index
,
const
struct
aty128fb_par
*
par
)
static
u32
_aty_ld_pll
(
unsigned
int
pll_index
,
const
struct
aty128fb_par
*
par
)
{
aty_st_8
(
CLOCK_CNTL_INDEX
,
pll_index
&
0x3F
);
return
aty_ld_le32
(
CLOCK_CNTL_DATA
);
}
static
void
_aty_st_pll
(
unsigned
int
pll_index
,
u32
val
,
static
void
_aty_st_pll
(
unsigned
int
pll_index
,
u32
val
,
const
struct
aty128fb_par
*
par
)
{
aty_st_8
(
CLOCK_CNTL_INDEX
,
(
pll_index
&
0x3F
)
|
PLL_WR_EN
);
...
...
@@ -492,15 +556,13 @@ _aty_st_pll(unsigned int pll_index, u32 val,
/* return true when the PLL has completed an atomic update */
static
int
aty_pll_readupdate
(
const
struct
aty128fb_par
*
par
)
static
int
aty_pll_readupdate
(
const
struct
aty128fb_par
*
par
)
{
return
!
(
aty_ld_pll
(
PPLL_REF_DIV
)
&
PPLL_ATOMIC_UPDATE_R
);
}
static
void
aty_pll_wait_readupdate
(
const
struct
aty128fb_par
*
par
)
static
void
aty_pll_wait_readupdate
(
const
struct
aty128fb_par
*
par
)
{
unsigned
long
timeout
=
jiffies
+
HZ
/
100
;
// should be more than enough
int
reset
=
1
;
...
...
@@ -517,8 +579,7 @@ aty_pll_wait_readupdate(const struct aty128fb_par *par)
/* tell PLL to update */
static
void
aty_pll_writeupdate
(
const
struct
aty128fb_par
*
par
)
static
void
aty_pll_writeupdate
(
const
struct
aty128fb_par
*
par
)
{
aty_pll_wait_readupdate
(
par
);
...
...
@@ -528,8 +589,7 @@ aty_pll_writeupdate(const struct aty128fb_par *par)
/* write to the scratch register to test r/w functionality */
static
int
__init
register_test
(
const
struct
aty128fb_par
*
par
)
static
int
__init
register_test
(
const
struct
aty128fb_par
*
par
)
{
u32
val
;
int
flag
=
0
;
...
...
@@ -552,8 +612,7 @@ register_test(const struct aty128fb_par *par)
/*
* Accelerator engine functions
*/
static
void
do_wait_for_fifo
(
u16
entries
,
struct
aty128fb_par
*
par
)
static
void
do_wait_for_fifo
(
u16
entries
,
struct
aty128fb_par
*
par
)
{
int
i
;
...
...
@@ -568,8 +627,7 @@ do_wait_for_fifo(u16 entries, struct aty128fb_par *par)
}
static
void
wait_for_idle
(
struct
aty128fb_par
*
par
)
static
void
wait_for_idle
(
struct
aty128fb_par
*
par
)
{
int
i
;
...
...
@@ -588,8 +646,7 @@ wait_for_idle(struct aty128fb_par *par)
}
static
void
wait_for_fifo
(
u16
entries
,
struct
aty128fb_par
*
par
)
static
void
wait_for_fifo
(
u16
entries
,
struct
aty128fb_par
*
par
)
{
if
(
par
->
fifo_slots
<
entries
)
do_wait_for_fifo
(
64
,
par
);
...
...
@@ -597,8 +654,7 @@ wait_for_fifo(u16 entries, struct aty128fb_par *par)
}
static
void
aty128_flush_pixel_cache
(
const
struct
aty128fb_par
*
par
)
static
void
aty128_flush_pixel_cache
(
const
struct
aty128fb_par
*
par
)
{
int
i
;
u32
tmp
;
...
...
@@ -614,8 +670,7 @@ aty128_flush_pixel_cache(const struct aty128fb_par *par)
}
static
void
aty128_reset_engine
(
const
struct
aty128fb_par
*
par
)
static
void
aty128_reset_engine
(
const
struct
aty128fb_par
*
par
)
{
u32
gen_reset_cntl
,
clock_cntl_index
,
mclk_cntl
;
...
...
@@ -643,8 +698,7 @@ aty128_reset_engine(const struct aty128fb_par *par)
}
static
void
aty128_init_engine
(
struct
aty128fb_par
*
par
)
static
void
aty128_init_engine
(
struct
aty128fb_par
*
par
)
{
u32
pitch_value
;
...
...
@@ -712,8 +766,7 @@ aty128_init_engine(struct aty128fb_par *par)
/* convert depth values to their register representation */
static
u32
depth_to_dst
(
u32
depth
)
static
u32
depth_to_dst
(
u32
depth
)
{
if
(
depth
<=
8
)
return
DST_8BPP
;
...
...
@@ -729,15 +782,247 @@ depth_to_dst(u32 depth)
return
-
EINVAL
;
}
/*
* PLL informations retreival
*/
#ifndef __sparc__
static
void
__init
aty128_unmap_ROM
(
struct
pci_dev
*
dev
,
void
*
rom
)
{
struct
resource
*
r
=
&
dev
->
resource
[
PCI_ROM_RESOURCE
];
iounmap
(
rom
);
/* Release the ROM resource if we used it in the first place */
if
(
r
->
parent
&&
r
->
flags
&
PCI_ROM_ADDRESS_ENABLE
)
{
release_resource
(
r
);
r
->
flags
&=
~
PCI_ROM_ADDRESS_ENABLE
;
r
->
end
-=
r
->
start
;
r
->
start
=
0
;
}
/* This will disable and set address to unassigned */
pci_write_config_dword
(
dev
,
dev
->
rom_base_reg
,
0
);
}
static
void
*
__init
aty128_map_ROM
(
const
struct
aty128fb_par
*
par
,
struct
pci_dev
*
dev
)
{
struct
resource
*
r
;
u16
dptr
;
u8
rom_type
;
void
*
bios
;
/* Fix from ATI for problem with Rage128 hardware not leaving ROM enabled */
unsigned
int
temp
;
temp
=
aty_ld_le32
(
RAGE128_MPP_TB_CONFIG
);
temp
&=
0x00ffffffu
;
temp
|=
0x04
<<
24
;
aty_st_le32
(
RAGE128_MPP_TB_CONFIG
,
temp
);
temp
=
aty_ld_le32
(
RAGE128_MPP_TB_CONFIG
);
/* no need to search for the ROM, just ask the card where it is. */
r
=
&
dev
->
resource
[
PCI_ROM_RESOURCE
];
/* assign the ROM an address if it doesn't have one */
if
(
r
->
parent
==
NULL
)
pci_assign_resource
(
dev
,
PCI_ROM_RESOURCE
);
/* enable if needed */
if
(
!
(
r
->
flags
&
PCI_ROM_ADDRESS_ENABLE
))
{
pci_write_config_dword
(
dev
,
dev
->
rom_base_reg
,
r
->
start
|
PCI_ROM_ADDRESS_ENABLE
);
r
->
flags
|=
PCI_ROM_ADDRESS_ENABLE
;
}
bios
=
ioremap
(
r
->
start
,
r
->
end
-
r
->
start
+
1
);
if
(
!
bios
)
{
printk
(
KERN_ERR
"aty128fb: ROM failed to map
\n
"
);
return
NULL
;
}
/* Very simple test to make sure it appeared */
if
(
BIOS_IN16
(
0
)
!=
0xaa55
)
{
printk
(
KERN_ERR
"aty128fb: Invalid ROM signature %x should be 0xaa55
\n
"
,
BIOS_IN16
(
0
));
goto
failed
;
}
/* Look for the PCI data to check the ROM type */
dptr
=
BIOS_IN16
(
0x18
);
/* Check the PCI data signature. If it's wrong, we still assume a normal x86 ROM
* for now, until I've verified this works everywhere. The goal here is more
* to phase out Open Firmware images.
*
* Currently, we only look at the first PCI data, we could iteratre and deal with
* them all, and we should use fb_bios_start relative to start of image and not
* relative start of ROM, but so far, I never found a dual-image ATI card
*
* typedef struct {
* u32 signature; + 0x00
* u16 vendor; + 0x04
* u16 device; + 0x06
* u16 reserved_1; + 0x08
* u16 dlen; + 0x0a
* u8 drevision; + 0x0c
* u8 class_hi; + 0x0d
* u16 class_lo; + 0x0e
* u16 ilen; + 0x10
* u16 irevision; + 0x12
* u8 type; + 0x14
* u8 indicator; + 0x15
* u16 reserved_2; + 0x16
* } pci_data_t;
*/
if
(
BIOS_IN32
(
dptr
)
!=
((
'R'
<<
24
)
|
(
'I'
<<
16
)
|
(
'C'
<<
8
)
|
'P'
))
{
printk
(
KERN_WARNING
"aty128fb: PCI DATA signature in ROM incorrect: %08x
\n
"
,
BIOS_IN32
(
dptr
));
goto
anyway
;
}
rom_type
=
BIOS_IN8
(
dptr
+
0x14
);
switch
(
rom_type
)
{
case
0
:
printk
(
KERN_INFO
"aty128fb: Found Intel x86 BIOS ROM Image
\n
"
);
break
;
case
1
:
printk
(
KERN_INFO
"aty128fb: Found Open Firmware ROM Image
\n
"
);
goto
failed
;
case
2
:
printk
(
KERN_INFO
"aty128fb: Found HP PA-RISC ROM Image
\n
"
);
goto
failed
;
default:
printk
(
KERN_INFO
"aty128fb: Found unknown type %d ROM Image
\n
"
,
rom_type
);
goto
failed
;
}
anyway:
return
bios
;
failed:
aty128_unmap_ROM
(
dev
,
bios
);
return
NULL
;
}
static
void
__init
aty128_get_pllinfo
(
struct
aty128fb_par
*
par
,
unsigned
char
*
bios
)
{
unsigned
int
bios_hdr
;
unsigned
int
bios_pll
;
bios_hdr
=
BIOS_IN16
(
0x48
);
bios_pll
=
BIOS_IN16
(
bios_hdr
+
0x30
);
par
->
constants
.
ppll_max
=
BIOS_IN32
(
bios_pll
+
0x16
);
par
->
constants
.
ppll_min
=
BIOS_IN32
(
bios_pll
+
0x12
);
par
->
constants
.
xclk
=
BIOS_IN16
(
bios_pll
+
0x08
);
par
->
constants
.
ref_divider
=
BIOS_IN16
(
bios_pll
+
0x10
);
par
->
constants
.
ref_clk
=
BIOS_IN16
(
bios_pll
+
0x0e
);
DBG
(
"ppll_max %d ppll_min %d xclk %d ref_divider %d ref clock %d
\n
"
,
par
->
constants
.
ppll_max
,
par
->
constants
.
ppll_min
,
par
->
constants
.
xclk
,
par
->
constants
.
ref_divider
,
par
->
constants
.
ref_clk
);
}
#ifdef __i386__
static
void
*
__devinit
aty128_find_mem_vbios
(
struct
aty128fb_par
*
par
)
{
/* I simplified this code as we used to miss the signatures in
* a lot of case. It's now closer to XFree, we just don't check
* for signatures at all... Something better will have to be done
* if we end up having conflicts
*/
u32
segstart
;
unsigned
char
*
rom_base
=
NULL
;
for
(
segstart
=
0x000c0000
;
segstart
<
0x000f0000
;
segstart
+=
0x00001000
)
{
rom_base
=
(
char
*
)
ioremap
(
segstart
,
0x10000
);
if
(
rom_base
==
NULL
)
return
NULL
;
if
((
*
rom_base
==
0x55
)
&&
(((
*
(
rom_base
+
1
))
&
0xff
)
==
0xaa
))
break
;
iounmap
(
rom_base
);
rom_base
=
NULL
;
}
return
rom_base
;
}
#endif
/* __i386__ */
#endif
/* ndef(__sparc__) */
/* fill in known card constants if pll_block is not available */
static
void
__init
aty128_timings
(
struct
aty128fb_par
*
par
)
{
#ifdef CONFIG_PPC_OF
/* instead of a table lookup, assume OF has properly
* setup the PLL registers and use their values
* to set the XCLK values and reference divider values */
u32
x_mpll_ref_fb_div
;
u32
xclk_cntl
;
u32
Nx
,
M
;
unsigned
PostDivSet
[]
=
{
0
,
1
,
2
,
4
,
8
,
3
,
6
,
12
};
#endif
if
(
!
par
->
constants
.
ref_clk
)
par
->
constants
.
ref_clk
=
2950
;
#ifdef CONFIG_PPC_OF
x_mpll_ref_fb_div
=
aty_ld_pll
(
X_MPLL_REF_FB_DIV
);
xclk_cntl
=
aty_ld_pll
(
XCLK_CNTL
)
&
0x7
;
Nx
=
(
x_mpll_ref_fb_div
&
0x00ff00
)
>>
8
;
M
=
x_mpll_ref_fb_div
&
0x0000ff
;
par
->
constants
.
xclk
=
round_div
((
2
*
Nx
*
par
->
constants
.
ref_clk
),
(
M
*
PostDivSet
[
xclk_cntl
]));
par
->
constants
.
ref_divider
=
aty_ld_pll
(
PPLL_REF_DIV
)
&
PPLL_REF_DIV_MASK
;
#endif
if
(
!
par
->
constants
.
ref_divider
)
{
par
->
constants
.
ref_divider
=
0x3b
;
aty_st_pll
(
X_MPLL_REF_FB_DIV
,
0x004c4c1e
);
aty_pll_writeupdate
(
par
);
}
aty_st_pll
(
PPLL_REF_DIV
,
par
->
constants
.
ref_divider
);
aty_pll_writeupdate
(
par
);
/* from documentation */
if
(
!
par
->
constants
.
ppll_min
)
par
->
constants
.
ppll_min
=
12500
;
if
(
!
par
->
constants
.
ppll_max
)
par
->
constants
.
ppll_max
=
25000
;
/* 23000 on some cards? */
if
(
!
par
->
constants
.
xclk
)
par
->
constants
.
xclk
=
0x1d4d
;
/* same as mclk */
par
->
constants
.
fifo_width
=
128
;
par
->
constants
.
fifo_depth
=
32
;
switch
(
aty_ld_le32
(
MEM_CNTL
)
&
0x3
)
{
case
0
:
par
->
mem
=
&
sdr_128
;
break
;
case
1
:
par
->
mem
=
&
sdr_sgram
;
break
;
case
2
:
par
->
mem
=
&
ddr_sgram
;
break
;
default:
par
->
mem
=
&
sdr_sgram
;
}
}
/*
* CRTC programming
*/
* CRTC programming
*/
/* Program the CRTC registers */
static
void
aty128_set_crtc
(
const
struct
aty128_crtc
*
crtc
,
const
struct
aty128fb_par
*
par
)
static
void
aty128_set_crtc
(
const
struct
aty128_crtc
*
crtc
,
const
struct
aty128fb_par
*
par
)
{
aty_st_le32
(
CRTC_GEN_CNTL
,
crtc
->
gen_cntl
);
aty_st_le32
(
CRTC_H_TOTAL_DISP
,
crtc
->
h_total
);
...
...
@@ -752,10 +1037,9 @@ aty128_set_crtc(const struct aty128_crtc *crtc,
}
static
int
aty128_var_to_crtc
(
const
struct
fb_var_screeninfo
*
var
,
struct
aty128_crtc
*
crtc
,
const
struct
aty128fb_par
*
par
)
static
int
aty128_var_to_crtc
(
const
struct
fb_var_screeninfo
*
var
,
struct
aty128_crtc
*
crtc
,
const
struct
aty128fb_par
*
par
)
{
u32
xres
,
yres
,
vxres
,
vyres
,
xoffset
,
yoffset
,
bpp
,
dst
;
u32
left
,
right
,
upper
,
lower
,
hslen
,
vslen
,
sync
,
vmode
;
...
...
@@ -881,8 +1165,7 @@ aty128_var_to_crtc(const struct fb_var_screeninfo *var,
}
static
int
aty128_pix_width_to_var
(
int
pix_width
,
struct
fb_var_screeninfo
*
var
)
static
int
aty128_pix_width_to_var
(
int
pix_width
,
struct
fb_var_screeninfo
*
var
)
{
/* fill in pixel info */
...
...
@@ -945,9 +1228,8 @@ aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var)
}
static
int
aty128_crtc_to_var
(
const
struct
aty128_crtc
*
crtc
,
struct
fb_var_screeninfo
*
var
)
static
int
aty128_crtc_to_var
(
const
struct
aty128_crtc
*
crtc
,
struct
fb_var_screeninfo
*
var
)
{
u32
xres
,
yres
,
left
,
right
,
upper
,
lower
,
hslen
,
vslen
,
sync
;
u32
h_total
,
h_disp
,
h_sync_strt
,
h_sync_dly
,
h_sync_wid
,
h_sync_pol
;
...
...
@@ -1003,8 +1285,7 @@ aty128_crtc_to_var(const struct aty128_crtc *crtc,
}
#ifdef CONFIG_PMAC_PBOOK
static
void
aty128_set_crt_enable
(
struct
aty128fb_par
*
par
,
int
on
)
static
void
aty128_set_crt_enable
(
struct
aty128fb_par
*
par
,
int
on
)
{
if
(
on
)
{
aty_st_le32
(
CRTC_EXT_CNTL
,
aty_ld_le32
(
CRTC_EXT_CNTL
)
|
CRT_CRTC_ON
);
...
...
@@ -1013,8 +1294,7 @@ aty128_set_crt_enable(struct aty128fb_par *par, int on)
aty_st_le32
(
CRTC_EXT_CNTL
,
aty_ld_le32
(
CRTC_EXT_CNTL
)
&
~
CRT_CRTC_ON
);
}
static
void
aty128_set_lcd_enable
(
struct
aty128fb_par
*
par
,
int
on
)
static
void
aty128_set_lcd_enable
(
struct
aty128fb_par
*
par
,
int
on
)
{
u32
reg
;
...
...
@@ -1039,10 +1319,9 @@ aty128_set_lcd_enable(struct aty128fb_par *par, int on)
aty_st_le32
(
LVDS_GEN_CNTL
,
reg
);
}
}
#endif
#endif
/* CONFIG_PMAC_PBOOK */
static
void
aty128_set_pll
(
struct
aty128_pll
*
pll
,
const
struct
aty128fb_par
*
par
)
static
void
aty128_set_pll
(
struct
aty128_pll
*
pll
,
const
struct
aty128fb_par
*
par
)
{
u32
div3
;
...
...
@@ -1081,9 +1360,8 @@ aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
}
static
int
aty128_var_to_pll
(
u32
period_in_ps
,
struct
aty128_pll
*
pll
,
const
struct
aty128fb_par
*
par
)
static
int
aty128_var_to_pll
(
u32
period_in_ps
,
struct
aty128_pll
*
pll
,
const
struct
aty128fb_par
*
par
)
{
const
struct
aty128_constants
c
=
par
->
constants
;
unsigned
char
post_dividers
[]
=
{
1
,
2
,
4
,
8
,
3
,
6
,
12
};
...
...
@@ -1109,7 +1387,7 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
/* calculate feedback divider */
n
=
c
.
ref_divider
*
output_freq
;
d
=
c
.
dotcloc
k
;
d
=
c
.
ref_cl
k
;
pll
->
post_divider
=
post_dividers
[
i
];
pll
->
feedback_divider
=
round_div
(
n
,
d
);
...
...
@@ -1124,8 +1402,7 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
}
static
int
aty128_pll_to_var
(
const
struct
aty128_pll
*
pll
,
struct
fb_var_screeninfo
*
var
)
static
int
aty128_pll_to_var
(
const
struct
aty128_pll
*
pll
,
struct
fb_var_screeninfo
*
var
)
{
var
->
pixclock
=
100000000
/
pll
->
vclk
;
...
...
@@ -1133,20 +1410,18 @@ aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var)
}
static
void
aty128_set_fifo
(
const
struct
aty128_ddafifo
*
dsp
,
const
struct
aty128fb_par
*
par
)
static
void
aty128_set_fifo
(
const
struct
aty128_ddafifo
*
dsp
,
const
struct
aty128fb_par
*
par
)
{
aty_st_le32
(
DDA_CONFIG
,
dsp
->
dda_config
);
aty_st_le32
(
DDA_ON_OFF
,
dsp
->
dda_on_off
);
}
static
int
aty128_ddafifo
(
struct
aty128_ddafifo
*
dsp
,
const
struct
aty128_pll
*
pll
,
u32
depth
,
const
struct
aty128fb_par
*
par
)
static
int
aty128_ddafifo
(
struct
aty128_ddafifo
*
dsp
,
const
struct
aty128_pll
*
pll
,
u32
depth
,
const
struct
aty128fb_par
*
par
)
{
const
struct
aty128_meminfo
*
m
=
par
->
mem
;
u32
xclk
=
par
->
constants
.
xclk
;
...
...
@@ -1203,8 +1478,7 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
/*
* This actually sets the video mode.
*/
static
int
aty128fb_set_par
(
struct
fb_info
*
info
)
static
int
aty128fb_set_par
(
struct
fb_info
*
info
)
{
struct
aty128fb_par
*
par
=
info
->
par
;
u32
config
;
...
...
@@ -1276,8 +1550,7 @@ aty128fb_set_par(struct fb_info *info)
* encode/decode the User Defined Part of the Display
*/
static
int
aty128_decode_var
(
struct
fb_var_screeninfo
*
var
,
struct
aty128fb_par
*
par
)
static
int
aty128_decode_var
(
struct
fb_var_screeninfo
*
var
,
struct
aty128fb_par
*
par
)
{
int
err
;
struct
aty128_crtc
crtc
;
...
...
@@ -1302,9 +1575,8 @@ aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par)
}
static
int
aty128_encode_var
(
struct
fb_var_screeninfo
*
var
,
const
struct
aty128fb_par
*
par
)
static
int
aty128_encode_var
(
struct
fb_var_screeninfo
*
var
,
const
struct
aty128fb_par
*
par
)
{
int
err
;
...
...
@@ -1325,8 +1597,7 @@ aty128_encode_var(struct fb_var_screeninfo *var,
}
static
int
aty128fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
static
int
aty128fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
{
struct
aty128fb_par
par
;
int
err
;
...
...
@@ -1342,8 +1613,7 @@ aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/*
* Pan or Wrap the Display
*/
static
int
aty128fb_pan_display
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
fb
)
static
int
aty128fb_pan_display
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
fb
)
{
struct
aty128fb_par
*
par
=
fb
->
par
;
u32
xoffset
,
yoffset
;
...
...
@@ -1376,9 +1646,8 @@ aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb)
/*
* Helper function to store a single palette register
*/
static
void
aty128_st_pal
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
struct
aty128fb_par
*
par
)
static
void
aty128_st_pal
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
struct
aty128fb_par
*
par
)
{
if
(
par
->
chip_gen
==
rage_M3
)
{
#if 0
...
...
@@ -1400,8 +1669,7 @@ aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue,
aty_st_le32
(
PALETTE_DATA
,
(
red
<<
16
)
|
(
green
<<
8
)
|
blue
);
}
static
int
aty128fb_sync
(
struct
fb_info
*
info
)
static
int
aty128fb_sync
(
struct
fb_info
*
info
)
{
struct
aty128fb_par
*
par
=
info
->
par
;
...
...
@@ -1410,8 +1678,7 @@ aty128fb_sync(struct fb_info *info)
return
0
;
}
int
__init
aty128fb_setup
(
char
*
options
)
int
__init
aty128fb_setup
(
char
*
options
)
{
char
*
this_opt
;
...
...
@@ -1470,13 +1737,12 @@ aty128fb_setup(char *options)
* Initialisation
*/
static
int
__init
aty128_init
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
static
int
__init
aty128_init
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
struct
fb_info
*
info
=
pci_get_drvdata
(
pdev
);
struct
aty128fb_par
*
par
=
info
->
par
;
struct
fb_var_screeninfo
var
;
char
video_card
[
25
];
char
video_card
[
DEVICE_NAME_SIZE
];
u8
chip_rev
;
u32
dac
;
...
...
@@ -1486,43 +1752,13 @@ aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Get the chip revision */
chip_rev
=
(
aty_ld_le32
(
CONFIG_CNTL
)
>>
16
)
&
0x1F
;
switch
(
pdev
->
device
)
{
case
PCI_DEVICE_ID_ATI_RAGE128_RE
:
strcpy
(
video_card
,
"Rage128 RE (PCI)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_RF
:
strcpy
(
video_card
,
"Rage128 RF (AGP)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_RK
:
strcpy
(
video_card
,
"Rage128 RK (PCI)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_RL
:
strcpy
(
video_card
,
"Rage128 RL (AGP)"
);
break
;
case
PCI_DEVICE_ID_ATI_Rage128_PD
:
strcpy
(
video_card
,
"Rage128 Pro PD (PCI)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_PF
:
strcpy
(
video_card
,
"Rage128 Pro PF (AGP)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_PR
:
strcpy
(
video_card
,
"Rage128 Pro PR (PCI)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_U3
:
strcpy
(
video_card
,
"Rage128 Pro TR (AGP)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_U1
:
strcpy
(
video_card
,
"Rage128 Pro TF (AGP)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_LE
:
strcpy
(
video_card
,
"Rage Mobility M3 (PCI)"
);
break
;
case
PCI_DEVICE_ID_ATI_RAGE128_LF
:
strcpy
(
video_card
,
"Rage Mobility M3 (AGP)"
);
break
;
default:
return
-
ENODEV
;
}
strcpy
(
video_card
,
"Rage128 XX "
);
video_card
[
8
]
=
ent
->
device
>>
8
;
video_card
[
9
]
=
ent
->
device
&
0xFF
;
/* range check to make sure */
if
(
ent
->
driver_data
<
(
sizeof
(
r128_family
)
/
sizeof
(
char
*
)))
strncat
(
video_card
,
r128_family
[
ent
->
driver_data
],
sizeof
(
video_card
));
printk
(
KERN_INFO
"aty128fb: %s [chip rev 0x%x] "
,
video_card
,
chip_rev
);
...
...
@@ -1575,8 +1811,12 @@ aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
if
(
machine_is_compatible
(
"PowerBook3,2"
))
default_vmode
=
VMODE_1152_768_60
;
if
(
default_cmode
<
CMODE_8
||
default_cmode
>
CMODE_32
)
default_cmode
=
CMODE_8
;
if
(
default_cmode
>
16
)
default_cmode
=
CMODE_32
;
else
if
(
default_cmode
>
8
)
default_cmode
=
CMODE_16
;
else
default_cmode
=
CMODE_8
;
if
(
mac_vmode_to_var
(
default_vmode
,
default_cmode
,
&
var
))
var
=
default_var
;
...
...
@@ -1584,9 +1824,10 @@ aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
}
else
#endif
/* CONFIG_PPC_PMAC */
{
if
(
fb_find_mode
(
&
var
,
info
,
mode_option
,
NULL
,
0
,
&
defaultmode
,
8
)
==
0
)
var
=
default_var
;
if
(
mode_option
)
if
(
fb_find_mode
(
&
var
,
info
,
mode_option
,
NULL
,
0
,
&
defaultmode
,
8
)
==
0
)
var
=
default_var
;
}
var
.
accel_flags
&=
~
FB_ACCELF_TEXT
;
...
...
@@ -1623,16 +1864,12 @@ aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
if
(
par
->
chip_gen
==
rage_M3
)
register_backlight_controller
(
&
aty128_backlight_controller
,
par
,
"ati"
);
#endif
/* CONFIG_PMAC_BACKLIGHT */
#ifdef CONFIG_PMAC_PBOOK
par
->
pm_reg
=
pci_find_capability
(
pdev
,
PCI_CAP_ID_PM
);
if
(
aty128_fb
==
NULL
)
{
/* XXX can only put one chip to sleep */
aty128_fb
=
info
;
}
else
printk
(
KERN_WARNING
"aty128fb: can only sleep one Rage 128
\n
"
);
par
->
pdev
=
pdev
;
#endif
par
->
asleep
=
0
;
par
->
lock_blank
=
0
;
printk
(
KERN_INFO
"fb%d: %s frame buffer device on %s
\n
"
,
info
->
node
,
info
->
fix
.
id
,
video_card
);
...
...
@@ -1641,14 +1878,13 @@ aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef CONFIG_PCI
/* register a card ++ajoshi */
static
int
__init
aty128_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
static
int
__init
aty128_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
unsigned
long
fb_addr
,
reg_addr
;
struct
aty128fb_par
*
par
;
struct
fb_info
*
info
;
int
err
,
size
;
#if
!defined(CONFIG_PPC) && !defined(__sparc__)
int
err
;
#if
ndef __sparc__
void
*
bios
=
NULL
;
#endif
...
...
@@ -1675,17 +1911,14 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* We have the resources. Now virtualize them */
size
=
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
aty128fb_par
);
if
(
!
(
info
=
kmalloc
(
size
,
GFP_ATOMIC
))
)
{
info
=
framebuffer_alloc
(
sizeof
(
struct
aty128fb_par
),
&
pdev
->
dev
);
if
(
info
==
NULL
)
{
printk
(
KERN_ERR
"aty128fb: can't alloc fb_info_aty128
\n
"
);
goto
err_free_mmio
;
}
memset
(
info
,
0
,
size
)
;
par
=
info
->
par
;
par
=
(
struct
aty128fb_par
*
)(
info
+
1
);
info
->
pseudo_palette
=
par
->
pseudo_palette
;
info
->
par
=
par
;
info
->
fix
=
aty128fb_fix
;
/* Virtualize mmio region */
...
...
@@ -1715,16 +1948,21 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto
err_out
;
}
#if !defined(CONFIG_PPC) && !defined(__sparc__)
if
(
!
(
bios
=
aty128_map_ROM
(
pdev
)))
#ifndef __sparc__
bios
=
aty128_map_ROM
(
par
,
pdev
);
#ifdef __i386__
if
(
bios
==
NULL
)
bios
=
aty128_find_mem_vbios
(
par
,
pdev
);
#endif
if
(
bios
==
NULL
)
printk
(
KERN_INFO
"aty128fb: BIOS not located, guessing timings.
\n
"
);
else
{
printk
(
KERN_INFO
"aty128fb: Rage128 BIOS located at %lx
\n
"
,
pdev
->
resource
[
PCI_ROM_RESOURCE
].
start
);
printk
(
KERN_INFO
"aty128fb: Rage128 BIOS located
\n
"
);
aty128_get_pllinfo
(
par
,
bios
);
aty128_unmap_ROM
(
pdev
,
bios
);
}
#endif
#endif
/* __sparc__ */
aty128_timings
(
par
);
pci_set_drvdata
(
pdev
,
info
);
...
...
@@ -1747,7 +1985,7 @@ aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_unmap_out:
iounmap
(
par
->
regbase
);
err_free_info:
kfre
e
(
info
);
framebuffer_releas
e
(
info
);
err_free_mmio:
release_mem_region
(
pci_resource_start
(
pdev
,
2
),
pci_resource_len
(
pdev
,
2
));
...
...
@@ -1780,170 +2018,23 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
pci_resource_len
(
pdev
,
1
));
release_mem_region
(
pci_resource_start
(
pdev
,
2
),
pci_resource_len
(
pdev
,
2
));
#ifdef CONFIG_PMAC_PBOOK
if
(
info
==
aty128_fb
)
aty128_fb
=
NULL
;
#endif
kfree
(
info
);
framebuffer_release
(
info
);
}
#endif
/* CONFIG_PCI */
/* PPC and Sparc cannot read video ROM */
#if !defined(CONFIG_PPC) && !defined(__sparc__)
static
void
*
__init
aty128_map_ROM
(
struct
pci_dev
*
dev
)
{
// If this is a primary card, there is a shadow copy of the
// ROM somewhere in the first meg. We will just ignore the copy
// and use the ROM directly.
// no need to search for the ROM, just ask the card where it is.
struct
resource
*
r
=
&
dev
->
resource
[
PCI_ROM_RESOURCE
];
unsigned
char
*
addr
;
// assign the ROM an address if it doesn't have one
if
(
r
->
start
==
0
)
pci_assign_resource
(
dev
,
PCI_ROM_RESOURCE
);
// enable if needed
if
(
!
(
r
->
flags
&
PCI_ROM_ADDRESS_ENABLE
))
pci_write_config_dword
(
dev
,
dev
->
rom_base_reg
,
r
->
start
|
PCI_ROM_ADDRESS_ENABLE
);
addr
=
ioremap
(
r
->
start
,
r
->
end
-
r
->
start
+
1
);
// Very simple test to make sure it appeared
if
(
addr
&&
(
*
addr
!=
0x55
))
{
printk
(
"aty128fb: Invalid ROM signature %x
\n
"
,
*
addr
);
iounmap
(
addr
);
return
NULL
;
}
return
(
void
*
)
addr
;
}
static
void
__init
aty128_unmap_ROM
(
struct
pci_dev
*
dev
,
void
*
rom
)
{
// leave it disabled and unassigned
struct
resource
*
r
=
&
dev
->
resource
[
PCI_ROM_RESOURCE
];
iounmap
(
rom
);
r
->
flags
&=
!
PCI_ROM_ADDRESS_ENABLE
;
r
->
end
-=
r
->
start
;
r
->
start
=
0
;
pci_write_config_dword
(
dev
,
dev
->
rom_base_reg
,
0
);
}
static
void
__init
aty128_get_pllinfo
(
struct
aty128fb_par
*
par
,
void
*
bios
)
{
void
*
bios_header
;
void
*
header_ptr
;
u16
bios_header_offset
,
pll_info_offset
;
PLL_BLOCK
pll
;
bios_header
=
(
char
*
)
bios
+
0x48L
;
header_ptr
=
bios_header
;
bios_header_offset
=
readw
(
header_ptr
);
bios_header
=
(
char
*
)
bios
+
bios_header_offset
;
bios_header
+=
0x30
;
header_ptr
=
bios_header
;
pll_info_offset
=
readw
(
header_ptr
);
header_ptr
=
(
char
*
)
bios
+
pll_info_offset
;
memcpy_fromio
(
&
pll
,
header_ptr
,
50
);
par
->
constants
.
ppll_max
=
pll
.
PCLK_max_freq
;
par
->
constants
.
ppll_min
=
pll
.
PCLK_min_freq
;
par
->
constants
.
xclk
=
(
u32
)
pll
.
XCLK
;
par
->
constants
.
ref_divider
=
(
u32
)
pll
.
PCLK_ref_divider
;
par
->
constants
.
dotclock
=
(
u32
)
pll
.
PCLK_ref_freq
;
DBG
(
"ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d
\n
"
,
par
->
constants
.
ppll_max
,
par
->
constants
.
ppll_min
,
par
->
constants
.
xclk
,
par
->
constants
.
ref_divider
,
par
->
constants
.
dotclock
);
}
#endif
/* !CONFIG_PPC */
/* fill in known card constants if pll_block is not available */
static
void
__init
aty128_timings
(
struct
aty128fb_par
*
par
)
{
#ifdef CONFIG_PPC_OF
/* instead of a table lookup, assume OF has properly
* setup the PLL registers and use their values
* to set the XCLK values and reference divider values */
u32
x_mpll_ref_fb_div
;
u32
xclk_cntl
;
u32
Nx
,
M
;
unsigned
PostDivSet
[]
=
{
0
,
1
,
2
,
4
,
8
,
3
,
6
,
12
};
#endif
if
(
!
par
->
constants
.
dotclock
)
par
->
constants
.
dotclock
=
2950
;
#ifdef CONFIG_PPC_OF
x_mpll_ref_fb_div
=
aty_ld_pll
(
X_MPLL_REF_FB_DIV
);
xclk_cntl
=
aty_ld_pll
(
XCLK_CNTL
)
&
0x7
;
Nx
=
(
x_mpll_ref_fb_div
&
0x00ff00
)
>>
8
;
M
=
x_mpll_ref_fb_div
&
0x0000ff
;
par
->
constants
.
xclk
=
round_div
((
2
*
Nx
*
par
->
constants
.
dotclock
),
(
M
*
PostDivSet
[
xclk_cntl
]));
par
->
constants
.
ref_divider
=
aty_ld_pll
(
PPLL_REF_DIV
)
&
PPLL_REF_DIV_MASK
;
#endif
if
(
!
par
->
constants
.
ref_divider
)
{
par
->
constants
.
ref_divider
=
0x3b
;
aty_st_pll
(
X_MPLL_REF_FB_DIV
,
0x004c4c1e
);
aty_pll_writeupdate
(
par
);
}
aty_st_pll
(
PPLL_REF_DIV
,
par
->
constants
.
ref_divider
);
aty_pll_writeupdate
(
par
);
/* from documentation */
if
(
!
par
->
constants
.
ppll_min
)
par
->
constants
.
ppll_min
=
12500
;
if
(
!
par
->
constants
.
ppll_max
)
par
->
constants
.
ppll_max
=
25000
;
/* 23000 on some cards? */
if
(
!
par
->
constants
.
xclk
)
par
->
constants
.
xclk
=
0x1d4d
;
/* same as mclk */
par
->
constants
.
fifo_width
=
128
;
par
->
constants
.
fifo_depth
=
32
;
switch
(
aty_ld_le32
(
MEM_CNTL
)
&
0x3
)
{
case
0
:
par
->
mem
=
&
sdr_128
;
break
;
case
1
:
par
->
mem
=
&
sdr_sgram
;
break
;
case
2
:
par
->
mem
=
&
ddr_sgram
;
break
;
default:
par
->
mem
=
&
sdr_sgram
;
}
}
/*
* Blank the display.
*/
static
int
aty128fb_blank
(
int
blank
,
struct
fb_info
*
fb
)
static
int
aty128fb_blank
(
int
blank
,
struct
fb_info
*
fb
)
{
struct
aty128fb_par
*
par
=
fb
->
par
;
u8
state
=
0
;
if
(
par
->
lock_blank
||
par
->
asleep
)
return
0
;
#ifdef CONFIG_PMAC_BACKLIGHT
if
((
_machine
==
_MACH_Pmac
)
&&
blank
)
set_backlight_enable
(
0
);
...
...
@@ -1976,9 +2067,8 @@ aty128fb_blank(int blank, struct fb_info *fb)
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
*/
static
int
aty128fb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
info
)
static
int
aty128fb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
info
)
{
struct
aty128fb_par
*
par
=
info
->
par
;
...
...
@@ -2041,9 +2131,9 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
#define ATY_MIRROR_CRT_ON 0x00000002
/* out param: u32* backlight value: 0 to 15 */
#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, __u32
*
)
#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, __u32)
/* in param: u32* backlight value: 0 to 15 */
#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32
*
)
#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32)
static
int
aty128fb_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
u_int
cmd
,
u_long
arg
,
struct
fb_info
*
info
)
...
...
@@ -2091,8 +2181,7 @@ static int backlight_conv[] = {
/* That one prevents proper CRT output with LCD off */
#undef BACKLIGHT_DAC_OFF
static
int
aty128_set_backlight_enable
(
int
on
,
int
level
,
void
*
data
)
static
int
aty128_set_backlight_enable
(
int
on
,
int
level
,
void
*
data
)
{
struct
aty128fb_par
*
par
=
data
;
unsigned
int
reg
=
aty_ld_le32
(
LVDS_GEN_CNTL
);
...
...
@@ -2139,8 +2228,7 @@ aty128_set_backlight_enable(int on, int level, void *data)
return
0
;
}
static
int
aty128_set_backlight_level
(
int
level
,
void
*
data
)
static
int
aty128_set_backlight_level
(
int
level
,
void
*
data
)
{
return
aty128_set_backlight_enable
(
1
,
level
,
data
);
}
...
...
@@ -2151,10 +2239,9 @@ aty128_set_backlight_level(int level, void* data)
* Accelerated functions
*/
static inline void
aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
u_int width, u_int height,
struct fb_info_aty128 *par)
static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
u_int width, u_int height,
struct fb_info_aty128 *par)
{
u32 save_dp_datatype, save_dp_cntl, dstval;
...
...
@@ -2196,8 +2283,7 @@ aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
* Text mode accelerated functions
*/
static void
fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
sx *= fontwidth(p);
...
...
@@ -2212,9 +2298,7 @@ fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
}
#endif /* 0 */
#ifdef CONFIG_PMAC_PBOOK
static
void
aty128_set_suspend
(
struct
aty128fb_par
*
par
,
int
suspend
)
static
void
aty128_set_suspend
(
struct
aty128fb_par
*
par
,
int
suspend
)
{
u32
pmgt
;
u16
pwr_command
;
...
...
@@ -2257,95 +2341,122 @@ aty128_set_suspend(struct aty128fb_par *par, int suspend)
}
}
/*
* Save the contents of the frame buffer when we go to sleep,
* and restore it when we wake up again.
*/
int
aty128_sleep_notify
(
struct
pmu_sleep_notifier
*
self
,
int
when
)
static
int
aty128_pci_suspend
(
struct
pci_dev
*
pdev
,
u32
state
)
{
int
nb
;
struct
fb_info
*
info
=
aty128_fb
;
struct
aty128fb_par
*
par
;
struct
fb_info
*
info
=
pci_get_drvdata
(
pdev
);
struct
aty128fb_par
*
par
=
info
->
par
;
if
(
info
==
NULL
)
return
PBOOK_SLEEP_OK
;
par
=
info
->
par
;
nb
=
info
->
var
.
yres
*
info
->
fix
.
line_length
;
/* We don't do anything but D2, for now we return 0, but
* we may want to change that. How do we know if the BIOS
* can properly take care of D3 ? Also, with swsusp, we
* know we'll be rebooted, ...
*/
#ifdef CONFIG_PPC_PMAC
/* HACK ALERT ! Once I find a proper way to say to each driver
* individually what will happen with it's PCI slot, I'll change
* that. On laptops, the AGP slot is just unclocked, so D2 is
* expected, while on desktops, the card is powered off
*/
if
(
state
>=
3
)
state
=
2
;
#endif
/* CONFIG_PPC_PMAC */
if
(
state
!=
2
||
state
==
pdev
->
dev
.
power_state
)
return
0
;
switch
(
when
)
{
case
PBOOK_SLEEP_REQUEST
:
par
->
save_framebuffer
=
vmalloc
(
nb
);
if
(
par
->
save_framebuffer
==
NULL
)
return
PBOOK_SLEEP_REFUSE
;
break
;
case
PBOOK_SLEEP_REJECT
:
if
(
par
->
save_framebuffer
)
{
vfree
(
par
->
save_framebuffer
);
par
->
save_framebuffer
=
0
;
}
break
;
case
PBOOK_SLEEP_NOW
:
wait_for_idle
(
par
);
aty128_reset_engine
(
par
);
wait_for_idle
(
par
);
printk
(
KERN_DEBUG
"aty128fb: suspending...
\n
"
);
acquire_console_sem
();
fb_set_suspend
(
info
,
1
);
/* Make sure engine is reset */
wait_for_idle
(
par
);
aty128_reset_engine
(
par
);
wait_for_idle
(
par
);
/* Backup fb content */
if
(
par
->
save_framebuffer
)
memcpy_fromio
(
par
->
save_framebuffer
,
info
->
screen_base
,
nb
);
/* Blank display and LCD */
aty128fb_blank
(
VESA_POWERDOWN
,
info
);
/* Blank display and LCD */
aty128fb_blank
(
VESA_POWERDOWN
,
info
);
/* Sleep the chip */
/* Sleep */
par
->
asleep
=
1
;
par
->
lock_blank
=
1
;
/* We need a way to make sure the fbdev layer will _not_ touch the
* framebuffer before we put the chip to suspend state. On 2.4, I
* used dummy fb ops, 2.5 need proper support for this at the
* fbdev level
*/
if
(
state
==
2
)
aty128_set_suspend
(
par
,
1
);
break
;
case
PBOOK_WAKE
:
/* Wake the chip */
release_console_sem
();
pdev
->
dev
.
power_state
=
state
;
return
0
;
}
static
int
aty128_pci_resume
(
struct
pci_dev
*
pdev
)
{
struct
fb_info
*
info
=
pci_get_drvdata
(
pdev
);
struct
aty128fb_par
*
par
=
info
->
par
;
if
(
pdev
->
dev
.
power_state
==
0
)
return
0
;
acquire_console_sem
();
/* Wakeup chip */
if
(
pdev
->
dev
.
power_state
==
2
)
aty128_set_suspend
(
par
,
0
);
aty128_reset_engine
(
par
);
wait_for_idle
(
par
);
par
->
asleep
=
0
;
/* Restore fb content */
if
(
par
->
save_framebuffer
)
{
memcpy_toio
(
info
->
screen_base
,
par
->
save_framebuffer
,
nb
);
vfree
(
par
->
save_framebuffer
);
par
->
save_framebuffer
=
0
;
}
aty128fb_blank
(
0
,
info
);
break
;
}
return
PBOOK_SLEEP_OK
;
/* Restore display & engine */
aty128_reset_engine
(
par
);
wait_for_idle
(
par
);
aty128fb_set_par
(
info
);
fb_pan_display
(
info
,
&
info
->
var
);
fb_set_cmap
(
&
info
->
cmap
,
1
,
info
);
/* Refresh */
fb_set_suspend
(
info
,
0
);
/* Unblank */
par
->
lock_blank
=
0
;
aty128fb_blank
(
0
,
info
);
release_console_sem
();
pdev
->
dev
.
power_state
=
0
;
printk
(
KERN_DEBUG
"aty128fb: resumed !
\n
"
);
return
0
;
}
#endif
/* CONFIG_PMAC_PBOOK */
int
__init
aty128fb_init
(
void
)
{
#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier
(
&
aty128_sleep_notifier
);
#endif
return
pci_module_init
(
&
aty128fb_driver
);
}
static
void
__exit
aty128fb_exit
(
void
)
{
#ifdef CONFIG_PMAC_PBOOK
pmu_unregister_sleep_notifier
(
&
aty128_sleep_notifier
);
#endif
pci_unregister_driver
(
&
aty128fb_driver
);
}
#ifdef MODULE
module_init
(
aty128fb_init
);
module_exit
(
aty128fb_exit
);
MODULE_AUTHOR
(
"(c)1999-2003 Brad Douglas <brad@neruo.com>"
);
MODULE_DESCRIPTION
(
"FBDev driver for ATI Rage128 / Pro cards"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
mode
,
"s"
);
module_param
(
mode_option
,
charp
,
0
);
MODULE_PARM_DESC
(
mode
,
"Specify resolution as
\"
<xres>x<yres>[-<bpp>][@<refresh>]
\"
"
);
#ifdef CONFIG_MTRR
MODULE_PARM
(
nomtrr
,
"i"
);
MODULE_PARM_DESC
(
nomtrr
,
"Disable MTRR support (0 or 1=disabled) (default=0)"
);
module_param_named
(
nomtrr
,
mtrr
,
invbool
,
0
);
MODULE_PARM_DESC
(
mtrr
,
"bool: Disable MTRR support (0 or 1=disabled) (default=0)"
);
#endif
#endif
drivers/video/aty/radeon_accel.c
View file @
d7203748
...
...
@@ -28,7 +28,7 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
struct
fb_fillrect
modded
;
int
vxres
,
vyres
;
if
(
rinfo
->
asleep
)
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
if
(
radeon_accel_disabled
())
{
cfb_fillrect
(
info
,
region
);
...
...
@@ -81,7 +81,7 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
modded
.
width
=
area
->
width
;
modded
.
height
=
area
->
height
;
if
(
rinfo
->
asleep
)
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
if
(
radeon_accel_disabled
())
{
cfb_copyarea
(
info
,
area
);
...
...
@@ -108,7 +108,7 @@ void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct
radeonfb_info
*
rinfo
=
info
->
par
;
if
(
rinfo
->
asleep
)
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
radeon_engine_idle
();
...
...
@@ -119,7 +119,7 @@ int radeonfb_sync(struct fb_info *info)
{
struct
radeonfb_info
*
rinfo
=
info
->
par
;
if
(
rinfo
->
asleep
)
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
0
;
radeon_engine_idle
();
...
...
drivers/video/aty/radeon_base.c
View file @
d7203748
...
...
@@ -566,8 +566,9 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
break
;
}
do_div
(
vclk
,
1000
);
xtal
=
(
xtal
*
denom
)
/
num
;
vclk
*=
denom
;
do_div
(
vclk
,
1000
*
num
);
xtal
=
vclk
;
if
((
xtal
>
26900
)
&&
(
xtal
<
27100
))
xtal
=
2700
;
...
...
drivers/video/cfbcopyarea.c
View file @
d7203748
...
...
@@ -346,6 +346,9 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
int
dst_idx
=
0
,
src_idx
=
0
,
rev_copy
=
0
;
unsigned
long
*
dst
=
NULL
,
*
src
=
NULL
;
if
(
p
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
/* We want rotation but lack hardware to do it for us. */
if
(
!
p
->
fbops
->
fb_rotate
&&
p
->
var
.
rotate
)
{
}
...
...
drivers/video/cfbfillrect.c
View file @
d7203748
...
...
@@ -367,6 +367,9 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
unsigned
long
*
dst
;
int
dst_idx
,
left
;
if
(
p
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
/* We want rotation but lack hardware to do it for us. */
if
(
!
p
->
fbops
->
fb_rotate
&&
p
->
var
.
rotate
)
{
}
...
...
drivers/video/cfbimgblt.c
View file @
d7203748
...
...
@@ -275,6 +275,9 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
int
x2
,
y2
,
vxres
,
vyres
;
u8
*
dst1
;
if
(
p
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
vxres
=
p
->
var
.
xres_virtual
;
vyres
=
p
->
var
.
yres_virtual
;
/*
...
...
drivers/video/console/fbcon.c
View file @
d7203748
...
...
@@ -195,11 +195,13 @@ static void fb_flashcursor(void *private)
{
struct
fb_info
*
info
=
(
struct
fb_info
*
)
private
;
/* Test to see if the cursor is erased but still on */
if
(
!
info
||
(
info
->
cursor
.
rop
==
ROP_COPY
)
)
if
(
!
info
||
info
->
state
!=
FBINFO_STATE_RUNNING
||
info
->
cursor
.
rop
==
ROP_COPY
)
return
;
acquire_console_sem
();
info
->
cursor
.
enable
^=
1
;
info
->
fbops
->
fb_cursor
(
info
,
&
info
->
cursor
);
release_console_sem
();
}
#if (defined(__arm__) && defined(IRQ_VSYNCPULSE)) || defined(CONFIG_ATARI) || defined(CONFIG_MAC)
...
...
@@ -226,8 +228,7 @@ static void cursor_timer_handler(unsigned long dev_addr)
struct
fb_info
*
info
=
(
struct
fb_info
*
)
dev_addr
;
schedule_work
(
&
info
->
queue
);
cursor_timer
.
expires
=
jiffies
+
HZ
/
5
;
add_timer
(
&
cursor_timer
);
mod_timer
(
&
cursor_timer
,
jiffies
+
HZ
/
5
);
}
int
__init
fb_console_setup
(
char
*
this_opt
)
...
...
@@ -353,8 +354,6 @@ static void putcs_unaligned(struct vc_data *vc, struct fb_info *info,
info
->
fbops
->
fb_imageblit
(
info
,
image
);
image
->
dx
+=
cnt
*
vc
->
vc_font
.
width
;
count
-=
cnt
;
atomic_dec
(
&
info
->
pixmap
.
count
);
smp_mb__after_atomic_dec
();
}
}
...
...
@@ -393,8 +392,6 @@ static void putcs_aligned(struct vc_data *vc, struct fb_info *info,
info
->
fbops
->
fb_imageblit
(
info
,
image
);
image
->
dx
+=
cnt
*
vc
->
vc_font
.
width
;
count
-=
cnt
;
atomic_dec
(
&
info
->
pixmap
.
count
);
smp_mb__after_atomic_dec
();
}
}
...
...
@@ -465,8 +462,6 @@ static void accel_putc(struct vc_data *vc, struct fb_info *info,
move_buf_aligned
(
info
,
dst
,
src
,
pitch
,
width
,
image
.
height
);
info
->
fbops
->
fb_imageblit
(
info
,
&
image
);
atomic_dec
(
&
info
->
pixmap
.
count
);
smp_mb__after_atomic_dec
();
}
void
accel_putcs
(
struct
vc_data
*
vc
,
struct
fb_info
*
info
,
...
...
@@ -676,7 +671,7 @@ static const char *fbcon_startup(void)
if
(
!
info
->
queue
.
func
)
{
INIT_WORK
(
&
info
->
queue
,
fb_flashcursor
,
info
);
cursor_timer
.
expires
=
jiffies
+
HZ
/
5
0
;
cursor_timer
.
expires
=
jiffies
+
HZ
/
5
;
cursor_timer
.
data
=
(
unsigned
long
)
info
;
add_timer
(
&
cursor_timer
);
}
...
...
@@ -944,6 +939,8 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
if
(
!
info
->
fbops
->
fb_blank
&&
console_blanked
)
return
;
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
if
(
!
height
||
!
width
)
return
;
...
...
@@ -968,6 +965,8 @@ static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
if
(
!
info
->
fbops
->
fb_blank
&&
console_blanked
)
return
;
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
if
(
vt_cons
[
vc
->
vc_num
]
->
vc_mode
!=
KD_TEXT
)
return
;
...
...
@@ -983,6 +982,8 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
if
(
!
info
->
fbops
->
fb_blank
&&
console_blanked
)
return
;
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
;
if
(
vt_cons
[
vc
->
vc_num
]
->
vc_mode
!=
KD_TEXT
)
return
;
...
...
@@ -2265,6 +2266,39 @@ static int fbcon_set_origin(struct vc_data *vc)
return
0
;
}
static
void
fbcon_suspended
(
struct
fb_info
*
info
)
{
/* Clear cursor, restore saved data */
info
->
cursor
.
enable
=
0
;
info
->
fbops
->
fb_cursor
(
info
,
&
info
->
cursor
);
}
static
void
fbcon_resumed
(
struct
fb_info
*
info
)
{
struct
vc_data
*
vc
;
if
(
info
->
currcon
<
0
)
return
;
vc
=
vc_cons
[
info
->
currcon
].
d
;
update_screen
(
vc
->
vc_num
);
}
static
int
fbcon_event_notify
(
struct
notifier_block
*
self
,
unsigned
long
action
,
void
*
data
)
{
struct
fb_info
*
info
=
(
struct
fb_info
*
)
data
;
switch
(
action
)
{
case
FB_EVENT_SUSPEND
:
fbcon_suspended
(
info
);
break
;
case
FB_EVENT_RESUME
:
fbcon_resumed
(
info
);
break
;
}
return
0
;
}
/*
* The console `switch' structure for the frame buffer based console
*/
...
...
@@ -2291,16 +2325,35 @@ const struct consw fb_con = {
.
con_resize
=
fbcon_resize
,
};
static
struct
notifier_block
fbcon_event_notifer
=
{
.
notifier_call
=
fbcon_event_notify
,
};
static
int
fbcon_event_notifier_registered
;
int
__init
fb_console_init
(
void
)
{
if
(
!
num_registered_fb
)
return
-
ENODEV
;
take_over_console
(
&
fb_con
,
first_fb_vc
,
last_fb_vc
,
fbcon_is_default
);
acquire_console_sem
();
if
(
!
fbcon_event_notifier_registered
)
{
fb_register_client
(
&
fbcon_event_notifer
);
fbcon_event_notifier_registered
=
1
;
}
release_console_sem
();
return
0
;
}
void
__exit
fb_console_exit
(
void
)
{
acquire_console_sem
();
if
(
fbcon_event_notifier_registered
)
{
fb_unregister_client
(
&
fbcon_event_notifer
);
fbcon_event_notifier_registered
=
0
;
}
release_console_sem
();
give_up_console
(
&
fb_con
);
}
...
...
drivers/video/fbmem.c
View file @
d7203748
...
...
@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/linux_logo.h>
#include <linux/proc_fs.h>
#include <linux/console.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
...
...
@@ -222,6 +223,9 @@ static struct {
#ifdef CONFIG_FB_RADEON
{
"radeonfb"
,
radeonfb_init
,
radeonfb_setup
},
#endif
#ifdef CONFIG_FB_RADEON_OLD
{
"radeonfb_old"
,
radeonfb_init
,
radeonfb_setup
},
#endif
#ifdef CONFIG_FB_CONTROL
{
"controlfb"
,
control_init
,
control_setup
},
#endif
...
...
@@ -395,6 +399,7 @@ extern const char *global_mode_option;
static
initcall_t
pref_init_funcs
[
FB_MAX
];
static
int
num_pref_init_funcs
__initdata
=
0
;
static
struct
notifier_block
*
fb_notifier_list
;
struct
fb_info
*
registered_fb
[
FB_MAX
];
int
num_registered_fb
;
...
...
@@ -463,23 +468,32 @@ void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
*/
u32
fb_get_buffer_offset
(
struct
fb_info
*
info
,
u32
size
)
{
u32
align
=
info
->
pixmap
.
buf_align
-
1
;
u32
offset
,
count
=
1000
;
struct
fb_pixmap
*
buf
=
&
info
->
pixmap
;
u32
align
=
buf
->
buf_align
-
1
,
offset
;
spin_lock
(
&
info
->
pixmap
.
lock
);
offset
=
info
->
pixmap
.
offset
+
align
;
/* If IO mapped, we need to sync before access, no sharing of
* the pixmap is done
*/
if
(
buf
->
flags
&
FB_PIXMAP_IO
)
{
if
(
info
->
fbops
->
fb_sync
&&
(
buf
->
flags
&
FB_PIXMAP_SYNC
))
info
->
fbops
->
fb_sync
(
info
);
return
0
;
}
/* See if we fit in the remaining pixmap space */
offset
=
buf
->
offset
+
align
;
offset
&=
~
align
;
if
(
offset
+
size
>
info
->
pixmap
.
size
)
{
while
(
atomic_read
(
&
info
->
pixmap
.
count
)
&&
count
--
);
if
(
info
->
fbops
->
fb_sync
&&
info
->
pixmap
.
flags
&
FB_PIXMAP_SYNC
)
if
(
offset
+
size
>
buf
->
size
)
{
/* We do not fit. In order to be able to re-use the buffer,
* we must ensure no asynchronous DMA'ing or whatever operation
* is in progress, we sync for that.
*/
if
(
info
->
fbops
->
fb_sync
&&
(
buf
->
flags
&
FB_PIXMAP_SYNC
))
info
->
fbops
->
fb_sync
(
info
);
offset
=
0
;
}
info
->
pixmap
.
offset
=
offset
+
size
;
atomic_inc
(
&
info
->
pixmap
.
count
);
smp_mb__after_atomic_inc
();
spin_unlock
(
&
info
->
pixmap
.
lock
);
buf
->
offset
=
offset
+
size
;
return
offset
;
}
...
...
@@ -685,8 +699,8 @@ int fb_show_logo(struct fb_info *info)
struct
fb_image
image
;
int
x
;
/* Return if the frame buffer is not mapped */
if
(
fb_logo
.
logo
==
NULL
)
/* Return if the frame buffer is not mapped
or suspended
*/
if
(
fb_logo
.
logo
==
NULL
||
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
0
;
image
.
depth
=
fb_logo
.
depth
;
...
...
@@ -732,8 +746,6 @@ int fb_show_logo(struct fb_info *info)
x
<=
info
->
var
.
xres
-
fb_logo
.
logo
->
width
;
x
+=
(
fb_logo
.
logo
->
width
+
8
))
{
image
.
dx
=
x
;
info
->
fbops
->
fb_imageblit
(
info
,
&
image
);
//atomic_dec(&info->pixmap.count);
//smp_mb__after_atomic_dec();
}
if
(
palette
!=
NULL
)
...
...
@@ -780,6 +792,9 @@ fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
if
(
!
info
||
!
info
->
screen_base
)
return
-
ENODEV
;
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
-
EPERM
;
if
(
info
->
fbops
->
fb_read
)
return
info
->
fbops
->
fb_read
(
file
,
buf
,
count
,
ppos
);
...
...
@@ -815,6 +830,9 @@ fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
if
(
!
info
||
!
info
->
screen_base
)
return
-
ENODEV
;
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
-
EPERM
;
if
(
info
->
fbops
->
fb_write
)
return
info
->
fbops
->
fb_write
(
file
,
buf
,
count
,
ppos
);
...
...
@@ -941,6 +959,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
fb_pan_display
(
info
,
&
info
->
var
);
fb_set_cmap
(
&
info
->
cmap
,
1
,
info
);
notifier_call_chain
(
&
fb_notifier_list
,
FB_EVENT_MODE_CHANGE
,
info
);
}
}
return
0
;
...
...
@@ -979,7 +999,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct
fb_con2fbmap
con2fb
;
#endif
struct
fb_cmap
cmap
;
int
i
;
int
i
,
rc
;
if
(
!
fb
)
return
-
ENODEV
;
...
...
@@ -990,7 +1010,9 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case
FBIOPUT_VSCREENINFO
:
if
(
copy_from_user
(
&
var
,
(
void
*
)
arg
,
sizeof
(
var
)))
return
-
EFAULT
;
acquire_console_sem
();
i
=
fb_set_var
(
info
,
&
var
);
release_console_sem
();
if
(
i
)
return
i
;
if
(
copy_to_user
((
void
*
)
arg
,
&
var
,
sizeof
(
var
)))
return
-
EFAULT
;
...
...
@@ -1009,13 +1031,19 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case
FBIOPAN_DISPLAY
:
if
(
copy_from_user
(
&
var
,
(
void
*
)
arg
,
sizeof
(
var
)))
return
-
EFAULT
;
if
((
i
=
fb_pan_display
(
info
,
&
var
)))
acquire_console_sem
();
i
=
fb_pan_display
(
info
,
&
var
);
release_console_sem
();
if
(
i
)
return
i
;
if
(
copy_to_user
((
void
*
)
arg
,
&
var
,
sizeof
(
var
)))
return
-
EFAULT
;
return
0
;
case
FBIO_CURSOR
:
return
(
fb_cursor
(
info
,
(
struct
fb_cursor
*
)
arg
));
acquire_console_sem
();
rc
=
fb_cursor
(
info
,
(
struct
fb_cursor
*
)
arg
);
release_console_sem
();
return
rc
;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
case
FBIOGET_CON2FBMAP
:
if
(
copy_from_user
(
&
con2fb
,
(
void
*
)
arg
,
sizeof
(
con2fb
)))
...
...
@@ -1045,7 +1073,10 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return
0
;
#endif
/* CONFIG_FRAMEBUFFER_CONSOLE */
case
FBIOBLANK
:
return
fb_blank
(
info
,
arg
);
acquire_console_sem
();
i
=
fb_blank
(
info
,
arg
);
release_console_sem
();
return
i
;
default:
if
(
fb
->
fb_ioctl
==
NULL
)
return
-
EINVAL
;
...
...
@@ -1242,7 +1273,6 @@ register_framebuffer(struct fb_info *fb_info)
fb_info
->
pixmap
.
outbuf
=
sys_outbuf
;
if
(
fb_info
->
pixmap
.
inbuf
==
NULL
)
fb_info
->
pixmap
.
inbuf
=
sys_inbuf
;
spin_lock_init
(
&
fb_info
->
pixmap
.
lock
);
registered_fb
[
i
]
=
fb_info
;
...
...
@@ -1279,8 +1309,42 @@ unregister_framebuffer(struct fb_info *fb_info)
return
0
;
}
/**
* fb_register_client - register a client notifier
* @nb: notifier block to callback on events
*/
int
fb_register_client
(
struct
notifier_block
*
nb
)
{
return
notifier_chain_register
(
&
fb_notifier_list
,
nb
);
}
/**
* fb_unregister_client - unregister a client notifier
* @nb: notifier block to callback on events
*/
int
fb_unregister_client
(
struct
notifier_block
*
nb
)
{
return
notifier_chain_unregister
(
&
fb_notifier_list
,
nb
);
}
/**
* fb_set_suspend - low level driver signals suspend
* @info: framebuffer affected
* @state: 0 = resuming, !=0 = suspending
*
* This is meant to be used by low level drivers to
* signal suspend/resume to the core & clients.
* It must be called with the console semaphore held
*/
void
fb_set_suspend
(
struct
fb_info
*
info
,
int
state
)
{
if
(
state
)
{
notifier_call_chain
(
&
fb_notifier_list
,
FB_EVENT_SUSPEND
,
info
);
info
->
state
=
FBINFO_STATE_SUSPENDED
;
}
else
{
info
->
state
=
FBINFO_STATE_RUNNING
;
notifier_call_chain
(
&
fb_notifier_list
,
FB_EVENT_RESUME
,
info
);
}
}
/**
...
...
@@ -1397,5 +1461,7 @@ EXPORT_SYMBOL(fb_get_buffer_offset);
EXPORT_SYMBOL
(
move_buf_unaligned
);
EXPORT_SYMBOL
(
move_buf_aligned
);
EXPORT_SYMBOL
(
fb_set_suspend
);
EXPORT_SYMBOL
(
fb_register_client
);
EXPORT_SYMBOL
(
fb_unregister_client
);
MODULE_LICENSE
(
"GPL"
);
drivers/video/riva/fbdev.c
View file @
d7203748
...
...
@@ -1615,8 +1615,9 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
}
#ifdef CONFIG_PPC_OF
static
int
riva_get_EDID_OF
(
struct
riva_par
*
par
,
struct
pci_dev
*
pd
)
static
int
riva_get_EDID_OF
(
struct
fb_info
*
info
,
struct
pci_dev
*
pd
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
struct
device_node
*
dp
;
unsigned
char
*
pedid
=
NULL
;
...
...
drivers/video/softcursor.c
View file @
d7203748
...
...
@@ -48,6 +48,9 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
info
->
cursor
.
image
.
depth
=
cursor
->
image
.
depth
;
}
if
(
info
->
state
!=
FBINFO_STATE_RUNNING
)
return
0
;
s_pitch
=
(
info
->
cursor
.
image
.
width
+
7
)
>>
3
;
dsize
=
s_pitch
*
info
->
cursor
.
image
.
height
;
d_pitch
=
(
s_pitch
+
scan_align
)
&
~
scan_align
;
...
...
@@ -74,8 +77,6 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
info
->
cursor
.
image
.
data
=
dst
;
info
->
fbops
->
fb_imageblit
(
info
,
&
info
->
cursor
.
image
);
atomic_dec
(
&
info
->
pixmap
.
count
);
smp_mb__after_atomic_dec
();
return
0
;
}
...
...
include/asm-ia64/mca.h
View file @
d7203748
...
...
@@ -114,7 +114,6 @@ extern void ia64_mca_ucmc_handler(void);
extern
void
ia64_monarch_init_handler
(
void
);
extern
void
ia64_slave_init_handler
(
void
);
extern
void
ia64_mca_cmc_vector_setup
(
void
);
extern
int
ia64_mca_check_errors
(
void
);
#endif
/* !__ASSEMBLY__ */
#endif
/* _ASM_IA64_MCA_H */
include/linux/fb.h
View file @
d7203748
...
...
@@ -339,6 +339,24 @@ struct fb_info;
struct
device
;
struct
file
;
/*
* Register/unregister for framebuffer events
*/
/* The resolution of the passed in fb_info about to change */
#define FB_EVENT_MODE_CHANGE 0x01
/* The display on this fb_info is beeing suspended, no access to the
* framebuffer is allowed any more after that call returns
*/
#define FB_EVENT_SUSPEND 0x02
/* The display on this fb_info was resumed, you can restore the display
* if you own it
*/
#define FB_EVENT_RESUME 0x03
extern
int
fb_register_client
(
struct
notifier_block
*
nb
);
extern
int
fb_unregister_client
(
struct
notifier_block
*
nb
);
/*
* Pixmap structure definition
*
...
...
@@ -363,8 +381,6 @@ struct fb_pixmap {
/* access methods */
void
(
*
outbuf
)(
u8
*
dst
,
u8
*
addr
,
unsigned
int
size
);
u8
(
*
inbuf
)
(
u8
*
addr
);
spinlock_t
lock
;
/* spinlock */
atomic_t
count
;
};
/*
...
...
@@ -449,6 +465,9 @@ struct fb_info {
struct
vc_data
*
display_fg
;
/* Console visible on this display */
int
currcon
;
/* Current VC. */
void
*
pseudo_palette
;
/* Fake palette of 16 colors */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32
state
;
/* Hardware state i.e suspend */
/* From here on everything is device dependent */
void
*
par
;
};
...
...
include/linux/pci_ids.h
View file @
d7203748
...
...
@@ -216,28 +216,37 @@
/* Rage128 GL */
#define PCI_DEVICE_ID_ATI_RAGE128_RE 0x5245
#define PCI_DEVICE_ID_ATI_RAGE128_RF 0x5246
#define PCI_DEVICE_ID_ATI_RAGE128_RG 0x534b
#define PCI_DEVICE_ID_ATI_RAGE128_RH 0x534c
#define PCI_DEVICE_ID_ATI_RAGE128_RI 0x534d
#define PCI_DEVICE_ID_ATI_RAGE128_RG 0x5247
/* Rage128 VR */
#define PCI_DEVICE_ID_ATI_RAGE128_RK 0x524b
#define PCI_DEVICE_ID_ATI_RAGE128_RL 0x524c
#define PCI_DEVICE_ID_ATI_RAGE128_RM 0x5345
#define PCI_DEVICE_ID_ATI_RAGE128_RN 0x5346
#define PCI_DEVICE_ID_ATI_RAGE128_RO 0x5347
#define PCI_DEVICE_ID_ATI_RAGE128_SE 0x5345
#define PCI_DEVICE_ID_ATI_RAGE128_SF 0x5346
#define PCI_DEVICE_ID_ATI_RAGE128_SG 0x5347
#define PCI_DEVICE_ID_ATI_RAGE128_SH 0x5348
#define PCI_DEVICE_ID_ATI_RAGE128_SK 0x534b
#define PCI_DEVICE_ID_ATI_RAGE128_SL 0x534c
#define PCI_DEVICE_ID_ATI_RAGE128_SM 0x534d
#define PCI_DEVICE_ID_ATI_RAGE128_SN 0x534e
/* Rage128 Ultra */
#define PCI_DEVICE_ID_ATI_RAGE128_TF 0x5446
#define PCI_DEVICE_ID_ATI_RAGE128_TL 0x544c
#define PCI_DEVICE_ID_ATI_RAGE128_TR 0x5452
#define PCI_DEVICE_ID_ATI_RAGE128_TS 0x5453
#define PCI_DEVICE_ID_ATI_RAGE128_TT 0x5454
#define PCI_DEVICE_ID_ATI_RAGE128_TU 0x5455
/* Rage128 M3 */
#define PCI_DEVICE_ID_ATI_RAGE128_LE 0x4c45
#define PCI_DEVICE_ID_ATI_RAGE128_LF 0x4c46
/* Rage128 Pro Ultra */
#define PCI_DEVICE_ID_ATI_RAGE128_U1 0x5446
#define PCI_DEVICE_ID_ATI_RAGE128_U2 0x544C
#define PCI_DEVICE_ID_ATI_RAGE128_U3 0x5452
/* Rage128 M4 */
#define PCI_DEVICE_ID_ATI_RAGE128_MF 0x4d46
#define PCI_DEVICE_ID_ATI_RAGE128_ML 0x4d4c
/* Rage128 Pro GL */
#define PCI_DEVICE_ID_ATI_R
age
128_PA 0x5041
#define PCI_DEVICE_ID_ATI_R
age
128_PB 0x5042
#define PCI_DEVICE_ID_ATI_R
age
128_PC 0x5043
#define PCI_DEVICE_ID_ATI_R
age
128_PD 0x5044
#define PCI_DEVICE_ID_ATI_R
age
128_PE 0x5045
#define PCI_DEVICE_ID_ATI_R
AGE
128_PA 0x5041
#define PCI_DEVICE_ID_ATI_R
AGE
128_PB 0x5042
#define PCI_DEVICE_ID_ATI_R
AGE
128_PC 0x5043
#define PCI_DEVICE_ID_ATI_R
AGE
128_PD 0x5044
#define PCI_DEVICE_ID_ATI_R
AGE
128_PE 0x5045
#define PCI_DEVICE_ID_ATI_RAGE128_PF 0x5046
/* Rage128 Pro VR */
#define PCI_DEVICE_ID_ATI_RAGE128_PG 0x5047
...
...
include/video/aty128.h
View file @
d7203748
...
...
@@ -415,5 +415,8 @@
#define PWR_MGT_SLOWDOWN_MCLK 0x00002000
#define PMI_PMSCR_REG 0x60
/* used by ATI bug fix for hardware ROM */
#define RAGE128_MPP_TB_CONFIG 0x01c0
#endif
/* REG_RAGE128_H */
net/bluetooth/rfcomm/tty.c
View file @
d7203748
...
...
@@ -97,10 +97,16 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
rfcomm_dlc_unlock
(
dlc
);
rfcomm_dlc_put
(
dlc
);
/* Refcount should only hit zero when called from rfcomm_dev_del()
which will have taken us off the list. Everything else are
refcounting bugs. */
BUG_ON
(
!
list_empty
(
&
dev
->
list
));
kfree
(
dev
);
/* It's safe to call module_put() here because socket still
holds ref
ference to this module. */
holds re
ference to this module. */
module_put
(
THIS_MODULE
);
}
...
...
@@ -111,6 +117,13 @@ static inline void rfcomm_dev_hold(struct rfcomm_dev *dev)
static
inline
void
rfcomm_dev_put
(
struct
rfcomm_dev
*
dev
)
{
/* The reason this isn't actually a race, as you no
doubt have a little voice screaming at you in your
head, is that the refcount should never actually
reach zero unless the device has already been taken
off the list, in rfcomm_dev_del(). And if that's not
true, we'll hit the BUG() in rfcomm_dev_destruct()
anyway. */
if
(
atomic_dec_and_test
(
&
dev
->
refcnt
))
rfcomm_dev_destruct
(
dev
);
}
...
...
@@ -134,10 +147,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
struct
rfcomm_dev
*
dev
;
read_lock
(
&
rfcomm_dev_lock
);
dev
=
__rfcomm_dev_get
(
id
);
if
(
dev
)
rfcomm_dev_hold
(
dev
);
read_unlock
(
&
rfcomm_dev_lock
);
if
(
dev
)
rfcomm_dev_hold
(
dev
);
return
dev
;
}
...
...
@@ -214,8 +230,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
rfcomm_dlc_unlock
(
dlc
);
/* It's safe to call __module_get() here because socket already
holds ref
ference to this module. */
holds re
ference to this module. */
__module_get
(
THIS_MODULE
);
out:
write_unlock_bh
(
&
rfcomm_dev_lock
);
...
...
@@ -486,7 +503,8 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
rfcomm_dev_del
(
dev
);
/* We have to drop DLC lock here, otherwise
* rfcomm_dev_put() will dead lock if it's the last refference */
rfcomm_dev_put() will dead lock if it's
the last reference. */
rfcomm_dlc_unlock
(
dlc
);
rfcomm_dev_put
(
dev
);
rfcomm_dlc_lock
(
dlc
);
...
...
@@ -541,6 +559,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
BT_DBG
(
"tty %p id %d"
,
tty
,
id
);
/* We don't leak this refcount. For reasons which are not entirely
clear, the TTY layer will call our ->close() method even if the
open fails. We decrease the refcount there, and decreasing it
here too would cause breakage. */
dev
=
rfcomm_dev_get
(
id
);
if
(
!
dev
)
return
-
ENODEV
;
...
...
@@ -561,10 +583,8 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
set_bit
(
RFCOMM_TTY_ATTACHED
,
&
dev
->
flags
);
err
=
rfcomm_dlc_open
(
dlc
,
&
dev
->
src
,
&
dev
->
dst
,
dev
->
channel
);
if
(
err
<
0
)
{
rfcomm_dev_put
(
dev
);
if
(
err
<
0
)
return
err
;
}
/* Wait for DLC to connect */
add_wait_queue
(
&
dev
->
wait
,
&
wait
);
...
...
@@ -589,9 +609,6 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
dev
->
wait
,
&
wait
);
if
(
err
<
0
)
rfcomm_dev_put
(
dev
);
return
err
;
}
...
...
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