Auto-update from upstream
This commit is contained in:
commit
55725495f2
|
@ -81,7 +81,8 @@ Adding New Machines
|
|||
|
||||
Any large scale modifications, or new drivers should be discussed
|
||||
on the ARM kernel mailing list (linux-arm-kernel) before being
|
||||
attempted.
|
||||
attempted. See http://www.arm.linux.org.uk/mailinglists/ for the
|
||||
mailing list information.
|
||||
|
||||
|
||||
NAND
|
||||
|
@ -120,6 +121,43 @@ Clock Management
|
|||
various clock units
|
||||
|
||||
|
||||
Platform Data
|
||||
-------------
|
||||
|
||||
Whenever a device has platform specific data that is specified
|
||||
on a per-machine basis, care should be taken to ensure the
|
||||
following:
|
||||
|
||||
1) that default data is not left in the device to confuse the
|
||||
driver if a machine does not set it at startup
|
||||
|
||||
2) the data should (if possible) be marked as __initdata,
|
||||
to ensure that the data is thrown away if the machine is
|
||||
not the one currently in use.
|
||||
|
||||
The best way of doing this is to make a function that
|
||||
kmalloc()s an area of memory, and copies the __initdata
|
||||
and then sets the relevant device's platform data. Making
|
||||
the function `__init` takes care of ensuring it is discarded
|
||||
with the rest of the initialisation code
|
||||
|
||||
static __init void s3c24xx_xxx_set_platdata(struct xxx_data *pd)
|
||||
{
|
||||
struct s3c2410_xxx_mach_info *npd;
|
||||
|
||||
npd = kmalloc(sizeof(struct s3c2410_xxx_mach_info), GFP_KERNEL);
|
||||
if (npd) {
|
||||
memcpy(npd, pd, sizeof(struct s3c2410_xxx_mach_info));
|
||||
s3c_device_xxx.dev.platform_data = npd;
|
||||
} else {
|
||||
printk(KERN_ERR "no memory for xxx platform data\n");
|
||||
}
|
||||
}
|
||||
|
||||
Note, since the code is marked as __init, it should not be
|
||||
exported outside arch/arm/mach-s3c2410/, or exported to
|
||||
modules via EXPORT_SYMBOL() and related functions.
|
||||
|
||||
Port Contributors
|
||||
-----------------
|
||||
|
||||
|
@ -149,6 +187,7 @@ Document Changes
|
|||
06 Mar 2005 - BJD - Added Christer Weinigel
|
||||
08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction
|
||||
08 Mar 2005 - BJD - Added section on adding machines
|
||||
09 Sep 2005 - BJD - Added section on platform data
|
||||
|
||||
Document Author
|
||||
---------------
|
||||
|
|
|
@ -116,12 +116,15 @@ hardware.
|
|||
line becoming inactive or the tty layer indicating we want
|
||||
to stop transmission due to an XOFF character.
|
||||
|
||||
The driver should stop transmitting characters as soon as
|
||||
possible.
|
||||
|
||||
Locking: port->lock taken.
|
||||
Interrupts: locally disabled.
|
||||
This call must not sleep
|
||||
|
||||
start_tx(port)
|
||||
start transmitting characters.
|
||||
Start transmitting characters.
|
||||
|
||||
Locking: port->lock taken.
|
||||
Interrupts: locally disabled.
|
||||
|
@ -281,26 +284,31 @@ hardware.
|
|||
Other functions
|
||||
---------------
|
||||
|
||||
uart_update_timeout(port,cflag,quot)
|
||||
uart_update_timeout(port,cflag,baud)
|
||||
Update the FIFO drain timeout, port->timeout, according to the
|
||||
number of bits, parity, stop bits and quotient.
|
||||
number of bits, parity, stop bits and baud rate.
|
||||
|
||||
Locking: caller is expected to take port->lock
|
||||
Interrupts: n/a
|
||||
|
||||
uart_get_baud_rate(port,termios)
|
||||
uart_get_baud_rate(port,termios,old,min,max)
|
||||
Return the numeric baud rate for the specified termios, taking
|
||||
account of the special 38400 baud "kludge". The B0 baud rate
|
||||
is mapped to 9600 baud.
|
||||
|
||||
If the baud rate is not within min..max, then if old is non-NULL,
|
||||
the original baud rate will be tried. If that exceeds the
|
||||
min..max constraint, 9600 baud will be returned. termios will
|
||||
be updated to the baud rate in use.
|
||||
|
||||
Note: min..max must always allow 9600 baud to be selected.
|
||||
|
||||
Locking: caller dependent.
|
||||
Interrupts: n/a
|
||||
|
||||
uart_get_divisor(port,termios,oldtermios)
|
||||
Return the divsor (baud_base / baud) for the selected baud rate
|
||||
specified by termios. If the baud rate is out of range, try
|
||||
the original baud rate specified by oldtermios (if non-NULL).
|
||||
If that fails, try 9600 baud.
|
||||
uart_get_divisor(port,baud)
|
||||
Return the divsor (baud_base / baud) for the specified baud
|
||||
rate, appropriately rounded.
|
||||
|
||||
If 38400 baud and custom divisor is selected, return the
|
||||
custom divisor instead.
|
||||
|
@ -308,6 +316,46 @@ uart_get_divisor(port,termios,oldtermios)
|
|||
Locking: caller dependent.
|
||||
Interrupts: n/a
|
||||
|
||||
uart_match_port(port1,port2)
|
||||
This utility function can be used to determine whether two
|
||||
uart_port structures describe the same port.
|
||||
|
||||
Locking: n/a
|
||||
Interrupts: n/a
|
||||
|
||||
uart_write_wakeup(port)
|
||||
A driver is expected to call this function when the number of
|
||||
characters in the transmit buffer have dropped below a threshold.
|
||||
|
||||
Locking: port->lock should be held.
|
||||
Interrupts: n/a
|
||||
|
||||
uart_register_driver(drv)
|
||||
Register a uart driver with the core driver. We in turn register
|
||||
with the tty layer, and initialise the core driver per-port state.
|
||||
|
||||
drv->port should be NULL, and the per-port structures should be
|
||||
registered using uart_add_one_port after this call has succeeded.
|
||||
|
||||
Locking: none
|
||||
Interrupts: enabled
|
||||
|
||||
uart_unregister_driver()
|
||||
Remove all references to a driver from the core driver. The low
|
||||
level driver must have removed all its ports via the
|
||||
uart_remove_one_port() if it registered them with uart_add_one_port().
|
||||
|
||||
Locking: none
|
||||
Interrupts: enabled
|
||||
|
||||
uart_suspend_port()
|
||||
|
||||
uart_resume_port()
|
||||
|
||||
uart_add_one_port()
|
||||
|
||||
uart_remove_one_port()
|
||||
|
||||
Other notes
|
||||
-----------
|
||||
|
||||
|
|
|
@ -194,6 +194,13 @@ config ARCH_VERSATILE
|
|||
help
|
||||
This enables support for ARM Ltd Versatile board.
|
||||
|
||||
config ARCH_REALVIEW
|
||||
bool "RealView"
|
||||
select ARM_AMBA
|
||||
select ICST307
|
||||
help
|
||||
This enables support for ARM Ltd RealView boards.
|
||||
|
||||
config ARCH_IMX
|
||||
bool "IMX"
|
||||
|
||||
|
@ -244,6 +251,8 @@ source "arch/arm/mach-versatile/Kconfig"
|
|||
|
||||
source "arch/arm/mach-aaec2000/Kconfig"
|
||||
|
||||
source "arch/arm/mach-realview/Kconfig"
|
||||
|
||||
# Definitions to make life easier
|
||||
config ARCH_ACORN
|
||||
bool
|
||||
|
@ -340,6 +349,13 @@ config NR_CPUS
|
|||
depends on SMP
|
||||
default "4"
|
||||
|
||||
config HOTPLUG_CPU
|
||||
bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
|
||||
depends on SMP && HOTPLUG && EXPERIMENTAL
|
||||
help
|
||||
Say Y here to experiment with turning CPUs off and on. CPUs
|
||||
can be controlled through /sys/devices/system/cpu.
|
||||
|
||||
config PREEMPT
|
||||
bool "Preemptible Kernel (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
|
|
|
@ -99,6 +99,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
|
|||
machine-$(CONFIG_ARCH_IMX) := imx
|
||||
machine-$(CONFIG_ARCH_H720X) := h720x
|
||||
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
|
||||
machine-$(CONFIG_ARCH_REALVIEW) := realview
|
||||
|
||||
ifeq ($(CONFIG_ARCH_EBSA110),y)
|
||||
# This is what happens if you forget the IOCS16 line.
|
||||
|
|
|
@ -104,7 +104,7 @@ CONFIG_ARCH_IXCDP1100=y
|
|||
CONFIG_ARCH_PRPMC1100=y
|
||||
CONFIG_ARCH_IXDP4XX=y
|
||||
CONFIG_CPU_IXP46X=y
|
||||
CONFIG_MACH_GTWX5715=y
|
||||
# CONFIG_MACH_GTWX5715 is not set
|
||||
|
||||
#
|
||||
# IXP4xx Options
|
||||
|
|
|
@ -1050,3 +1050,34 @@ static int __init noirqdebug_setup(char *str)
|
|||
}
|
||||
|
||||
__setup("noirqdebug", noirqdebug_setup);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/*
|
||||
* The CPU has been marked offline. Migrate IRQs off this CPU. If
|
||||
* the affinity settings do not allow other CPUs, force them onto any
|
||||
* available CPU.
|
||||
*/
|
||||
void migrate_irqs(void)
|
||||
{
|
||||
unsigned int i, cpu = smp_processor_id();
|
||||
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
struct irqdesc *desc = irq_desc + i;
|
||||
|
||||
if (desc->cpu == cpu) {
|
||||
unsigned int newcpu = any_online_cpu(desc->affinity);
|
||||
|
||||
if (newcpu == NR_CPUS) {
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n",
|
||||
i, cpu);
|
||||
|
||||
cpus_setall(desc->affinity);
|
||||
newcpu = any_online_cpu(desc->affinity);
|
||||
}
|
||||
|
||||
route_irq(desc, i, newcpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -105,6 +106,14 @@ void cpu_idle(void)
|
|||
/* endless idle loop with no priority at all */
|
||||
while (1) {
|
||||
void (*idle)(void) = pm_idle;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
if (cpu_is_offline(smp_processor_id())) {
|
||||
leds_event(led_idle_start);
|
||||
cpu_die();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!idle)
|
||||
idle = default_idle;
|
||||
preempt_disable();
|
||||
|
|
|
@ -80,19 +80,23 @@ static DEFINE_SPINLOCK(smp_call_function_lock);
|
|||
|
||||
int __cpuinit __cpu_up(unsigned int cpu)
|
||||
{
|
||||
struct task_struct *idle;
|
||||
struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
|
||||
struct task_struct *idle = ci->idle;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Spawn a new process manually. Grab a pointer to
|
||||
* its task struct so we can mess with it
|
||||
* Spawn a new process manually, if not already done.
|
||||
* Grab a pointer to its task struct so we can mess with it
|
||||
*/
|
||||
idle = fork_idle(cpu);
|
||||
if (IS_ERR(idle)) {
|
||||
printk(KERN_ERR "CPU%u: fork() failed\n", cpu);
|
||||
return PTR_ERR(idle);
|
||||
if (!idle) {
|
||||
idle = fork_idle(cpu);
|
||||
if (IS_ERR(idle)) {
|
||||
printk(KERN_ERR "CPU%u: fork() failed\n", cpu);
|
||||
return PTR_ERR(idle);
|
||||
}
|
||||
ci->idle = idle;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -155,6 +159,91 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/*
|
||||
* __cpu_disable runs on the processor to be shutdown.
|
||||
*/
|
||||
int __cpuexit __cpu_disable(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct task_struct *p;
|
||||
int ret;
|
||||
|
||||
ret = mach_cpu_disable(cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Take this CPU offline. Once we clear this, we can't return,
|
||||
* and we must not schedule until we're ready to give up the cpu.
|
||||
*/
|
||||
cpu_clear(cpu, cpu_online_map);
|
||||
|
||||
/*
|
||||
* OK - migrate IRQs away from this CPU
|
||||
*/
|
||||
migrate_irqs();
|
||||
|
||||
/*
|
||||
* Flush user cache and TLB mappings, and then remove this CPU
|
||||
* from the vm mask set of all processes.
|
||||
*/
|
||||
flush_cache_all();
|
||||
local_flush_tlb_all();
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
for_each_process(p) {
|
||||
if (p->mm)
|
||||
cpu_clear(cpu, p->mm->cpu_vm_mask);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* called on the thread which is asking for a CPU to be shutdown -
|
||||
* waits until shutdown has completed, or it is timed out.
|
||||
*/
|
||||
void __cpuexit __cpu_die(unsigned int cpu)
|
||||
{
|
||||
if (!platform_cpu_kill(cpu))
|
||||
printk("CPU%u: unable to kill\n", cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from the idle thread for the CPU which has been shutdown.
|
||||
*
|
||||
* Note that we disable IRQs here, but do not re-enable them
|
||||
* before returning to the caller. This is also the behaviour
|
||||
* of the other hotplug-cpu capable cores, so presumably coming
|
||||
* out of idle fixes this.
|
||||
*/
|
||||
void __cpuexit cpu_die(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
local_irq_disable();
|
||||
idle_task_exit();
|
||||
|
||||
/*
|
||||
* actual CPU shutdown procedure is at least platform (if not
|
||||
* CPU) specific
|
||||
*/
|
||||
platform_cpu_die(cpu);
|
||||
|
||||
/*
|
||||
* Do not return to the idle loop - jump back to the secondary
|
||||
* cpu initialisation. There's some initialisation which needs
|
||||
* to be repeated to undo the effects of taking the CPU offline.
|
||||
*/
|
||||
__asm__("mov sp, %0\n"
|
||||
" b secondary_start_kernel"
|
||||
:
|
||||
: "r" ((void *)current->thread_info + THREAD_SIZE - 8));
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
/*
|
||||
* This is the secondary CPU boot entry. We're using this CPUs
|
||||
* idle thread stack, but a set of temporary page tables.
|
||||
|
@ -236,6 +325,8 @@ void __init smp_prepare_boot_cpu(void)
|
|||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
per_cpu(cpu_data, cpu).idle = current;
|
||||
|
||||
cpu_set(cpu, cpu_possible_map);
|
||||
cpu_set(cpu, cpu_present_map);
|
||||
cpu_set(cpu, cpu_online_map);
|
||||
|
@ -309,8 +400,8 @@ int smp_call_function_on_cpu(void (*func)(void *info), void *info, int retry,
|
|||
printk(KERN_CRIT
|
||||
"CPU%u: smp_call_function timeout for %p(%p)\n"
|
||||
" callmap %lx pending %lx, %swait\n",
|
||||
smp_processor_id(), func, info, callmap, data.pending,
|
||||
wait ? "" : "no ");
|
||||
smp_processor_id(), func, info, *cpus_addr(callmap),
|
||||
*cpus_addr(data.pending), wait ? "" : "no ");
|
||||
|
||||
/*
|
||||
* TRACE
|
||||
|
|
|
@ -7,13 +7,27 @@
|
|||
lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
|
||||
csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
|
||||
copy_page.o delay.o findbit.o memchr.o memcpy.o \
|
||||
memset.o memzero.o setbit.o strncpy_from_user.o \
|
||||
strnlen_user.o strchr.o strrchr.o testchangebit.o \
|
||||
testclearbit.o testsetbit.o uaccess.o getuser.o \
|
||||
putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
|
||||
memmove.o memset.o memzero.o setbit.o \
|
||||
strncpy_from_user.o strnlen_user.o \
|
||||
strchr.o strrchr.o \
|
||||
testchangebit.o testclearbit.o testsetbit.o \
|
||||
getuser.o putuser.o clear_user.o \
|
||||
ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
|
||||
ucmpdi2.o lib1funcs.o div64.o sha1.o \
|
||||
io-readsb.o io-writesb.o io-readsl.o io-writesl.o
|
||||
|
||||
# the code in uaccess.S is not preemption safe and
|
||||
# probably faster on ARMv3 only
|
||||
ifeq ($CONFIG_PREEMPT,y)
|
||||
lib-y += copy_from_user.o copy_to_user.o
|
||||
else
|
||||
ifneq ($(CONFIG_CPU_32v3),y)
|
||||
lib-y += copy_from_user.o copy_to_user.o
|
||||
else
|
||||
lib-y += uaccess.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CPU_32v3),y)
|
||||
lib-y += io-readsw-armv3.o io-writesw-armv3.o
|
||||
else
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* linux/arch/arm/lib/clear_user.S
|
||||
*
|
||||
* Copyright (C) 1995, 1996,1997,1998 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
.text
|
||||
|
||||
/* Prototype: int __arch_clear_user(void *addr, size_t sz)
|
||||
* Purpose : clear some user memory
|
||||
* Params : addr - user memory address to clear
|
||||
* : sz - number of bytes to clear
|
||||
* Returns : number of bytes NOT cleared
|
||||
*/
|
||||
ENTRY(__arch_clear_user)
|
||||
stmfd sp!, {r1, lr}
|
||||
mov r2, #0
|
||||
cmp r1, #4
|
||||
blt 2f
|
||||
ands ip, r0, #3
|
||||
beq 1f
|
||||
cmp ip, #2
|
||||
USER( strbt r2, [r0], #1)
|
||||
USER( strlebt r2, [r0], #1)
|
||||
USER( strltbt r2, [r0], #1)
|
||||
rsb ip, ip, #4
|
||||
sub r1, r1, ip @ 7 6 5 4 3 2 1
|
||||
1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
|
||||
USER( strplt r2, [r0], #4)
|
||||
USER( strplt r2, [r0], #4)
|
||||
bpl 1b
|
||||
adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
|
||||
USER( strplt r2, [r0], #4)
|
||||
2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
|
||||
USER( strnebt r2, [r0], #1)
|
||||
USER( strnebt r2, [r0], #1)
|
||||
tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
|
||||
USER( strnebt r2, [r0], #1)
|
||||
mov r0, #0
|
||||
LOADREGS(fd,sp!, {r1, pc})
|
||||
|
||||
.section .fixup,"ax"
|
||||
.align 0
|
||||
9001: LOADREGS(fd,sp!, {r0, pc})
|
||||
.previous
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* linux/arch/arm/lib/copy_from_user.S
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Sep 29, 2005
|
||||
* Copyright: MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
/*
|
||||
* Prototype:
|
||||
*
|
||||
* size_t __arch_copy_from_user(void *to, const void *from, size_t n)
|
||||
*
|
||||
* Purpose:
|
||||
*
|
||||
* copy a block to kernel memory from user memory
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* to = kernel memory
|
||||
* from = user memory
|
||||
* n = number of bytes to copy
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Number of bytes NOT copied.
|
||||
*/
|
||||
|
||||
.macro ldr1w ptr reg abort
|
||||
100: ldrt \reg, [\ptr], #4
|
||||
.section __ex_table, "a"
|
||||
.long 100b, \abort
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
|
||||
ldr1w \ptr, \reg1, \abort
|
||||
ldr1w \ptr, \reg2, \abort
|
||||
ldr1w \ptr, \reg3, \abort
|
||||
ldr1w \ptr, \reg4, \abort
|
||||
.endm
|
||||
|
||||
.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
ldr4w \ptr, \reg1, \reg2, \reg3, \reg4, \abort
|
||||
ldr4w \ptr, \reg5, \reg6, \reg7, \reg8, \abort
|
||||
.endm
|
||||
|
||||
.macro ldr1b ptr reg cond=al abort
|
||||
100: ldr\cond\()bt \reg, [\ptr], #1
|
||||
.section __ex_table, "a"
|
||||
.long 100b, \abort
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.macro str1w ptr reg abort
|
||||
str \reg, [\ptr], #4
|
||||
.endm
|
||||
|
||||
.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
|
||||
.endm
|
||||
|
||||
.macro str1b ptr reg cond=al abort
|
||||
str\cond\()b \reg, [\ptr], #1
|
||||
.endm
|
||||
|
||||
.macro enter reg1 reg2
|
||||
mov r3, #0
|
||||
stmdb sp!, {r0, r2, r3, \reg1, \reg2}
|
||||
.endm
|
||||
|
||||
.macro exit reg1 reg2
|
||||
add sp, sp, #8
|
||||
ldmfd sp!, {r0, \reg1, \reg2}
|
||||
.endm
|
||||
|
||||
.text
|
||||
|
||||
ENTRY(__arch_copy_from_user)
|
||||
|
||||
#include "copy_template.S"
|
||||
|
||||
.section .fixup,"ax"
|
||||
.align 0
|
||||
copy_abort_preamble
|
||||
ldmfd sp!, {r1, r2}
|
||||
sub r3, r0, r1
|
||||
rsb r1, r3, r2
|
||||
str r1, [sp]
|
||||
bl __memzero
|
||||
ldr r0, [sp], #4
|
||||
copy_abort_end
|
||||
.previous
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* linux/arch/arm/lib/copy_template.s
|
||||
*
|
||||
* Code template for optimized memory copy functions
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Sep 28, 2005
|
||||
* Copyright: MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This can be used to enable code to cacheline align the source pointer.
|
||||
* Experiments on tested architectures (StrongARM and XScale) didn't show
|
||||
* this a worthwhile thing to do. That might be different in the future.
|
||||
*/
|
||||
//#define CALGN(code...) code
|
||||
#define CALGN(code...)
|
||||
|
||||
/*
|
||||
* Theory of operation
|
||||
* -------------------
|
||||
*
|
||||
* This file provides the core code for a forward memory copy used in
|
||||
* the implementation of memcopy(), copy_to_user() and copy_from_user().
|
||||
*
|
||||
* The including file must define the following accessor macros
|
||||
* according to the need of the given function:
|
||||
*
|
||||
* ldr1w ptr reg abort
|
||||
*
|
||||
* This loads one word from 'ptr', stores it in 'reg' and increments
|
||||
* 'ptr' to the next word. The 'abort' argument is used for fixup tables.
|
||||
*
|
||||
* ldr4w ptr reg1 reg2 reg3 reg4 abort
|
||||
* ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
*
|
||||
* This loads four or eight words starting from 'ptr', stores them
|
||||
* in provided registers and increments 'ptr' past those words.
|
||||
* The'abort' argument is used for fixup tables.
|
||||
*
|
||||
* ldr1b ptr reg cond abort
|
||||
*
|
||||
* Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
|
||||
* It also must apply the condition code if provided, otherwise the
|
||||
* "al" condition is assumed by default.
|
||||
*
|
||||
* str1w ptr reg abort
|
||||
* str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
* str1b ptr reg cond abort
|
||||
*
|
||||
* Same as their ldr* counterparts, but data is stored to 'ptr' location
|
||||
* rather than being loaded.
|
||||
*
|
||||
* enter reg1 reg2
|
||||
*
|
||||
* Preserve the provided registers on the stack plus any additional
|
||||
* data as needed by the implementation including this code. Called
|
||||
* upon code entry.
|
||||
*
|
||||
* exit reg1 reg2
|
||||
*
|
||||
* Restore registers with the values previously saved with the
|
||||
* 'preserv' macro. Called upon code termination.
|
||||
*/
|
||||
|
||||
|
||||
enter r4, lr
|
||||
|
||||
subs r2, r2, #4
|
||||
blt 8f
|
||||
ands ip, r0, #3
|
||||
PLD( pld [r1, #0] )
|
||||
bne 9f
|
||||
ands ip, r1, #3
|
||||
bne 10f
|
||||
|
||||
1: subs r2, r2, #(28)
|
||||
stmfd sp!, {r5 - r8}
|
||||
blt 5f
|
||||
|
||||
CALGN( ands ip, r1, #31 )
|
||||
CALGN( rsb r3, ip, #32 )
|
||||
CALGN( sbcnes r4, r3, r2 ) @ C is always set here
|
||||
CALGN( bcs 2f )
|
||||
CALGN( adr r4, 6f )
|
||||
CALGN( subs r2, r2, r3 ) @ C gets set
|
||||
CALGN( add pc, r4, ip )
|
||||
|
||||
PLD( pld [r1, #0] )
|
||||
2: PLD( subs r2, r2, #96 )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( blt 4f )
|
||||
PLD( pld [r1, #60] )
|
||||
PLD( pld [r1, #92] )
|
||||
|
||||
3: PLD( pld [r1, #124] )
|
||||
4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
|
||||
subs r2, r2, #32
|
||||
str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
|
||||
bge 3b
|
||||
PLD( cmn r2, #96 )
|
||||
PLD( bge 4b )
|
||||
|
||||
5: ands ip, r2, #28
|
||||
rsb ip, ip, #32
|
||||
addne pc, pc, ip @ C is always clear here
|
||||
b 7f
|
||||
6: nop
|
||||
ldr1w r1, r3, abort=20f
|
||||
ldr1w r1, r4, abort=20f
|
||||
ldr1w r1, r5, abort=20f
|
||||
ldr1w r1, r6, abort=20f
|
||||
ldr1w r1, r7, abort=20f
|
||||
ldr1w r1, r8, abort=20f
|
||||
ldr1w r1, lr, abort=20f
|
||||
|
||||
add pc, pc, ip
|
||||
nop
|
||||
nop
|
||||
str1w r0, r3, abort=20f
|
||||
str1w r0, r4, abort=20f
|
||||
str1w r0, r5, abort=20f
|
||||
str1w r0, r6, abort=20f
|
||||
str1w r0, r7, abort=20f
|
||||
str1w r0, r8, abort=20f
|
||||
str1w r0, lr, abort=20f
|
||||
|
||||
CALGN( bcs 2b )
|
||||
|
||||
7: ldmfd sp!, {r5 - r8}
|
||||
|
||||
8: movs r2, r2, lsl #31
|
||||
ldr1b r1, r3, ne, abort=21f
|
||||
ldr1b r1, r4, cs, abort=21f
|
||||
ldr1b r1, ip, cs, abort=21f
|
||||
str1b r0, r3, ne, abort=21f
|
||||
str1b r0, r4, cs, abort=21f
|
||||
str1b r0, ip, cs, abort=21f
|
||||
|
||||
exit r4, pc
|
||||
|
||||
9: rsb ip, ip, #4
|
||||
cmp ip, #2
|
||||
ldr1b r1, r3, gt, abort=21f
|
||||
ldr1b r1, r4, ge, abort=21f
|
||||
ldr1b r1, lr, abort=21f
|
||||
str1b r0, r3, gt, abort=21f
|
||||
str1b r0, r4, ge, abort=21f
|
||||
subs r2, r2, ip
|
||||
str1b r0, lr, abort=21f
|
||||
blt 8b
|
||||
ands ip, r1, #3
|
||||
beq 1b
|
||||
|
||||
10: bic r1, r1, #3
|
||||
cmp ip, #2
|
||||
ldr1w r1, lr, abort=21f
|
||||
beq 17f
|
||||
bgt 18f
|
||||
|
||||
|
||||
.macro forward_copy_shift pull push
|
||||
|
||||
subs r2, r2, #28
|
||||
blt 14f
|
||||
|
||||
CALGN( ands ip, r1, #31 )
|
||||
CALGN( rsb ip, ip, #32 )
|
||||
CALGN( sbcnes r4, ip, r2 ) @ C is always set here
|
||||
CALGN( subcc r2, r2, ip )
|
||||
CALGN( bcc 15f )
|
||||
|
||||
11: stmfd sp!, {r5 - r9}
|
||||
|
||||
PLD( pld [r1, #0] )
|
||||
PLD( subs r2, r2, #96 )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( blt 13f )
|
||||
PLD( pld [r1, #60] )
|
||||
PLD( pld [r1, #92] )
|
||||
|
||||
12: PLD( pld [r1, #124] )
|
||||
13: ldr4w r1, r4, r5, r6, r7, abort=19f
|
||||
mov r3, lr, pull #\pull
|
||||
subs r2, r2, #32
|
||||
ldr4w r1, r8, r9, ip, lr, abort=19f
|
||||
orr r3, r3, r4, push #\push
|
||||
mov r4, r4, pull #\pull
|
||||
orr r4, r4, r5, push #\push
|
||||
mov r5, r5, pull #\pull
|
||||
orr r5, r5, r6, push #\push
|
||||
mov r6, r6, pull #\pull
|
||||
orr r6, r6, r7, push #\push
|
||||
mov r7, r7, pull #\pull
|
||||
orr r7, r7, r8, push #\push
|
||||
mov r8, r8, pull #\pull
|
||||
orr r8, r8, r9, push #\push
|
||||
mov r9, r9, pull #\pull
|
||||
orr r9, r9, ip, push #\push
|
||||
mov ip, ip, pull #\pull
|
||||
orr ip, ip, lr, push #\push
|
||||
str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
|
||||
bge 12b
|
||||
PLD( cmn r2, #96 )
|
||||
PLD( bge 13b )
|
||||
|
||||
ldmfd sp!, {r5 - r9}
|
||||
|
||||
14: ands ip, r2, #28
|
||||
beq 16f
|
||||
|
||||
15: mov r3, lr, pull #\pull
|
||||
ldr1w r1, lr, abort=21f
|
||||
subs ip, ip, #4
|
||||
orr r3, r3, lr, push #\push
|
||||
str1w r0, r3, abort=21f
|
||||
bgt 15b
|
||||
CALGN( cmp r2, #0 )
|
||||
CALGN( bge 11b )
|
||||
|
||||
16: sub r1, r1, #(\push / 8)
|
||||
b 8b
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
forward_copy_shift pull=8 push=24
|
||||
|
||||
17: forward_copy_shift pull=16 push=16
|
||||
|
||||
18: forward_copy_shift pull=24 push=8
|
||||
|
||||
|
||||
/*
|
||||
* Abort preanble and completion macros.
|
||||
* If a fixup handler is required then those macros must surround it.
|
||||
* It is assumed that the fixup code will handle the private part of
|
||||
* the exit macro.
|
||||
*/
|
||||
|
||||
.macro copy_abort_preamble
|
||||
19: ldmfd sp!, {r5 - r9}
|
||||
b 21f
|
||||
20: ldmfd sp!, {r5 - r8}
|
||||
21:
|
||||
.endm
|
||||
|
||||
.macro copy_abort_end
|
||||
ldmfd sp!, {r4, pc}
|
||||
.endm
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* linux/arch/arm/lib/copy_to_user.S
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Sep 29, 2005
|
||||
* Copyright: MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
/*
|
||||
* Prototype:
|
||||
*
|
||||
* size_t __arch_copy_to_user(void *to, const void *from, size_t n)
|
||||
*
|
||||
* Purpose:
|
||||
*
|
||||
* copy a block to user memory from kernel memory
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* to = user memory
|
||||
* from = kernel memory
|
||||
* n = number of bytes to copy
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* Number of bytes NOT copied.
|
||||
*/
|
||||
|
||||
.macro ldr1w ptr reg abort
|
||||
ldr \reg, [\ptr], #4
|
||||
.endm
|
||||
|
||||
.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
|
||||
ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
|
||||
.endm
|
||||
|
||||
.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
|
||||
.endm
|
||||
|
||||
.macro ldr1b ptr reg cond=al abort
|
||||
ldr\cond\()b \reg, [\ptr], #1
|
||||
.endm
|
||||
|
||||
.macro str1w ptr reg abort
|
||||
100: strt \reg, [\ptr], #4
|
||||
.section __ex_table, "a"
|
||||
.long 100b, \abort
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
str1w \ptr, \reg1, \abort
|
||||
str1w \ptr, \reg2, \abort
|
||||
str1w \ptr, \reg3, \abort
|
||||
str1w \ptr, \reg4, \abort
|
||||
str1w \ptr, \reg5, \abort
|
||||
str1w \ptr, \reg6, \abort
|
||||
str1w \ptr, \reg7, \abort
|
||||
str1w \ptr, \reg8, \abort
|
||||
.endm
|
||||
|
||||
.macro str1b ptr reg cond=al abort
|
||||
100: str\cond\()bt \reg, [\ptr], #1
|
||||
.section __ex_table, "a"
|
||||
.long 100b, \abort
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.macro enter reg1 reg2
|
||||
mov r3, #0
|
||||
stmdb sp!, {r0, r2, r3, \reg1, \reg2}
|
||||
.endm
|
||||
|
||||
.macro exit reg1 reg2
|
||||
add sp, sp, #8
|
||||
ldmfd sp!, {r0, \reg1, \reg2}
|
||||
.endm
|
||||
|
||||
.text
|
||||
|
||||
ENTRY(__arch_copy_to_user)
|
||||
|
||||
#include "copy_template.S"
|
||||
|
||||
.section .fixup,"ax"
|
||||
.align 0
|
||||
copy_abort_preamble
|
||||
ldmfd sp!, {r1, r2, r3}
|
||||
sub r0, r0, r1
|
||||
rsb r0, r0, r2
|
||||
copy_abort_end
|
||||
.previous
|
||||
|
|
@ -1,393 +1,59 @@
|
|||
/*
|
||||
* linux/arch/arm/lib/memcpy.S
|
||||
*
|
||||
* Copyright (C) 1995-1999 Russell King
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Sep 28, 2005
|
||||
* Copyright: MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* ASM optimised string functions
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
.text
|
||||
.macro ldr1w ptr reg abort
|
||||
ldr \reg, [\ptr], #4
|
||||
.endm
|
||||
|
||||
#define ENTER \
|
||||
mov ip,sp ;\
|
||||
stmfd sp!,{r0,r4-r9,fp,ip,lr,pc} ;\
|
||||
sub fp,ip,#4
|
||||
.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
|
||||
ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
|
||||
.endm
|
||||
|
||||
#define EXIT \
|
||||
LOADREGS(ea, fp, {r0, r4 - r9, fp, sp, pc})
|
||||
.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
|
||||
.endm
|
||||
|
||||
#define EXITEQ \
|
||||
LOADREGS(eqea, fp, {r0, r4 - r9, fp, sp, pc})
|
||||
.macro ldr1b ptr reg cond=al abort
|
||||
ldr\cond\()b \reg, [\ptr], #1
|
||||
.endm
|
||||
|
||||
.macro str1w ptr reg abort
|
||||
str \reg, [\ptr], #4
|
||||
.endm
|
||||
|
||||
.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
|
||||
.endm
|
||||
|
||||
.macro str1b ptr reg cond=al abort
|
||||
str\cond\()b \reg, [\ptr], #1
|
||||
.endm
|
||||
|
||||
.macro enter reg1 reg2
|
||||
stmdb sp!, {r0, \reg1, \reg2}
|
||||
.endm
|
||||
|
||||
.macro exit reg1 reg2
|
||||
ldmfd sp!, {r0, \reg1, \reg2}
|
||||
.endm
|
||||
|
||||
.text
|
||||
|
||||
/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
|
||||
|
||||
/*
|
||||
* Prototype: void memcpy(void *to,const void *from,unsigned long n);
|
||||
*/
|
||||
ENTRY(memcpy)
|
||||
ENTRY(memmove)
|
||||
ENTER
|
||||
cmp r1, r0
|
||||
bcc 23f
|
||||
subs r2, r2, #4
|
||||
blt 6f
|
||||
PLD( pld [r1, #0] )
|
||||
ands ip, r0, #3
|
||||
bne 7f
|
||||
ands ip, r1, #3
|
||||
bne 8f
|
||||
|
||||
1: subs r2, r2, #8
|
||||
blt 5f
|
||||
subs r2, r2, #20
|
||||
blt 4f
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( subs r2, r2, #64 )
|
||||
PLD( blt 3f )
|
||||
2: PLD( pld [r1, #60] )
|
||||
PLD( pld [r1, #92] )
|
||||
ldmia r1!, {r3 - r9, ip}
|
||||
subs r2, r2, #32
|
||||
stmgeia r0!, {r3 - r9, ip}
|
||||
ldmgeia r1!, {r3 - r9, ip}
|
||||
subges r2, r2, #32
|
||||
stmia r0!, {r3 - r9, ip}
|
||||
bge 2b
|
||||
3: PLD( ldmia r1!, {r3 - r9, ip} )
|
||||
PLD( adds r2, r2, #32 )
|
||||
PLD( stmgeia r0!, {r3 - r9, ip} )
|
||||
PLD( ldmgeia r1!, {r3 - r9, ip} )
|
||||
PLD( subges r2, r2, #32 )
|
||||
PLD( stmia r0!, {r3 - r9, ip} )
|
||||
4: cmn r2, #16
|
||||
ldmgeia r1!, {r3 - r6}
|
||||
subge r2, r2, #16
|
||||
stmgeia r0!, {r3 - r6}
|
||||
adds r2, r2, #20
|
||||
ldmgeia r1!, {r3 - r5}
|
||||
subge r2, r2, #12
|
||||
stmgeia r0!, {r3 - r5}
|
||||
5: adds r2, r2, #8
|
||||
blt 6f
|
||||
subs r2, r2, #4
|
||||
ldrlt r3, [r1], #4
|
||||
ldmgeia r1!, {r4, r5}
|
||||
subge r2, r2, #4
|
||||
strlt r3, [r0], #4
|
||||
stmgeia r0!, {r4, r5}
|
||||
|
||||
6: adds r2, r2, #4
|
||||
EXITEQ
|
||||
cmp r2, #2
|
||||
ldrb r3, [r1], #1
|
||||
ldrgeb r4, [r1], #1
|
||||
ldrgtb r5, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
strgeb r4, [r0], #1
|
||||
strgtb r5, [r0], #1
|
||||
EXIT
|
||||
|
||||
7: rsb ip, ip, #4
|
||||
cmp ip, #2
|
||||
ldrb r3, [r1], #1
|
||||
ldrgeb r4, [r1], #1
|
||||
ldrgtb r5, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
strgeb r4, [r0], #1
|
||||
strgtb r5, [r0], #1
|
||||
subs r2, r2, ip
|
||||
blt 6b
|
||||
ands ip, r1, #3
|
||||
beq 1b
|
||||
|
||||
8: bic r1, r1, #3
|
||||
ldr r7, [r1], #4
|
||||
cmp ip, #2
|
||||
bgt 18f
|
||||
beq 13f
|
||||
cmp r2, #12
|
||||
blt 11f
|
||||
PLD( pld [r1, #12] )
|
||||
sub r2, r2, #12
|
||||
PLD( subs r2, r2, #32 )
|
||||
PLD( blt 10f )
|
||||
PLD( pld [r1, #28] )
|
||||
9: PLD( pld [r1, #44] )
|
||||
10: mov r3, r7, pull #8
|
||||
ldmia r1!, {r4 - r7}
|
||||
subs r2, r2, #16
|
||||
orr r3, r3, r4, push #24
|
||||
mov r4, r4, pull #8
|
||||
orr r4, r4, r5, push #24
|
||||
mov r5, r5, pull #8
|
||||
orr r5, r5, r6, push #24
|
||||
mov r6, r6, pull #8
|
||||
orr r6, r6, r7, push #24
|
||||
stmia r0!, {r3 - r6}
|
||||
bge 9b
|
||||
PLD( cmn r2, #32 )
|
||||
PLD( bge 10b )
|
||||
PLD( add r2, r2, #32 )
|
||||
adds r2, r2, #12
|
||||
blt 12f
|
||||
11: mov r3, r7, pull #8
|
||||
ldr r7, [r1], #4
|
||||
subs r2, r2, #4
|
||||
orr r3, r3, r7, push #24
|
||||
str r3, [r0], #4
|
||||
bge 11b
|
||||
12: sub r1, r1, #3
|
||||
b 6b
|
||||
|
||||
13: cmp r2, #12
|
||||
blt 16f
|
||||
PLD( pld [r1, #12] )
|
||||
sub r2, r2, #12
|
||||
PLD( subs r2, r2, #32 )
|
||||
PLD( blt 15f )
|
||||
PLD( pld [r1, #28] )
|
||||
14: PLD( pld [r1, #44] )
|
||||
15: mov r3, r7, pull #16
|
||||
ldmia r1!, {r4 - r7}
|
||||
subs r2, r2, #16
|
||||
orr r3, r3, r4, push #16
|
||||
mov r4, r4, pull #16
|
||||
orr r4, r4, r5, push #16
|
||||
mov r5, r5, pull #16
|
||||
orr r5, r5, r6, push #16
|
||||
mov r6, r6, pull #16
|
||||
orr r6, r6, r7, push #16
|
||||
stmia r0!, {r3 - r6}
|
||||
bge 14b
|
||||
PLD( cmn r2, #32 )
|
||||
PLD( bge 15b )
|
||||
PLD( add r2, r2, #32 )
|
||||
adds r2, r2, #12
|
||||
blt 17f
|
||||
16: mov r3, r7, pull #16
|
||||
ldr r7, [r1], #4
|
||||
subs r2, r2, #4
|
||||
orr r3, r3, r7, push #16
|
||||
str r3, [r0], #4
|
||||
bge 16b
|
||||
17: sub r1, r1, #2
|
||||
b 6b
|
||||
|
||||
18: cmp r2, #12
|
||||
blt 21f
|
||||
PLD( pld [r1, #12] )
|
||||
sub r2, r2, #12
|
||||
PLD( subs r2, r2, #32 )
|
||||
PLD( blt 20f )
|
||||
PLD( pld [r1, #28] )
|
||||
19: PLD( pld [r1, #44] )
|
||||
20: mov r3, r7, pull #24
|
||||
ldmia r1!, {r4 - r7}
|
||||
subs r2, r2, #16
|
||||
orr r3, r3, r4, push #8
|
||||
mov r4, r4, pull #24
|
||||
orr r4, r4, r5, push #8
|
||||
mov r5, r5, pull #24
|
||||
orr r5, r5, r6, push #8
|
||||
mov r6, r6, pull #24
|
||||
orr r6, r6, r7, push #8
|
||||
stmia r0!, {r3 - r6}
|
||||
bge 19b
|
||||
PLD( cmn r2, #32 )
|
||||
PLD( bge 20b )
|
||||
PLD( add r2, r2, #32 )
|
||||
adds r2, r2, #12
|
||||
blt 22f
|
||||
21: mov r3, r7, pull #24
|
||||
ldr r7, [r1], #4
|
||||
subs r2, r2, #4
|
||||
orr r3, r3, r7, push #8
|
||||
str r3, [r0], #4
|
||||
bge 21b
|
||||
22: sub r1, r1, #1
|
||||
b 6b
|
||||
|
||||
|
||||
23: add r1, r1, r2
|
||||
add r0, r0, r2
|
||||
subs r2, r2, #4
|
||||
blt 29f
|
||||
PLD( pld [r1, #-4] )
|
||||
ands ip, r0, #3
|
||||
bne 30f
|
||||
ands ip, r1, #3
|
||||
bne 31f
|
||||
|
||||
24: subs r2, r2, #8
|
||||
blt 28f
|
||||
subs r2, r2, #20
|
||||
blt 27f
|
||||
PLD( pld [r1, #-32] )
|
||||
PLD( subs r2, r2, #64 )
|
||||
PLD( blt 26f )
|
||||
25: PLD( pld [r1, #-64] )
|
||||
PLD( pld [r1, #-96] )
|
||||
ldmdb r1!, {r3 - r9, ip}
|
||||
subs r2, r2, #32
|
||||
stmgedb r0!, {r3 - r9, ip}
|
||||
ldmgedb r1!, {r3 - r9, ip}
|
||||
subges r2, r2, #32
|
||||
stmdb r0!, {r3 - r9, ip}
|
||||
bge 25b
|
||||
26: PLD( ldmdb r1!, {r3 - r9, ip} )
|
||||
PLD( adds r2, r2, #32 )
|
||||
PLD( stmgedb r0!, {r3 - r9, ip} )
|
||||
PLD( ldmgedb r1!, {r3 - r9, ip} )
|
||||
PLD( subges r2, r2, #32 )
|
||||
PLD( stmdb r0!, {r3 - r9, ip} )
|
||||
27: cmn r2, #16
|
||||
ldmgedb r1!, {r3 - r6}
|
||||
subge r2, r2, #16
|
||||
stmgedb r0!, {r3 - r6}
|
||||
adds r2, r2, #20
|
||||
ldmgedb r1!, {r3 - r5}
|
||||
subge r2, r2, #12
|
||||
stmgedb r0!, {r3 - r5}
|
||||
28: adds r2, r2, #8
|
||||
blt 29f
|
||||
subs r2, r2, #4
|
||||
ldrlt r3, [r1, #-4]!
|
||||
ldmgedb r1!, {r4, r5}
|
||||
subge r2, r2, #4
|
||||
strlt r3, [r0, #-4]!
|
||||
stmgedb r0!, {r4, r5}
|
||||
|
||||
29: adds r2, r2, #4
|
||||
EXITEQ
|
||||
cmp r2, #2
|
||||
ldrb r3, [r1, #-1]!
|
||||
ldrgeb r4, [r1, #-1]!
|
||||
ldrgtb r5, [r1, #-1]!
|
||||
strb r3, [r0, #-1]!
|
||||
strgeb r4, [r0, #-1]!
|
||||
strgtb r5, [r0, #-1]!
|
||||
EXIT
|
||||
|
||||
30: cmp ip, #2
|
||||
ldrb r3, [r1, #-1]!
|
||||
ldrgeb r4, [r1, #-1]!
|
||||
ldrgtb r5, [r1, #-1]!
|
||||
strb r3, [r0, #-1]!
|
||||
strgeb r4, [r0, #-1]!
|
||||
strgtb r5, [r0, #-1]!
|
||||
subs r2, r2, ip
|
||||
blt 29b
|
||||
ands ip, r1, #3
|
||||
beq 24b
|
||||
|
||||
31: bic r1, r1, #3
|
||||
ldr r3, [r1], #0
|
||||
cmp ip, #2
|
||||
blt 41f
|
||||
beq 36f
|
||||
cmp r2, #12
|
||||
blt 34f
|
||||
PLD( pld [r1, #-16] )
|
||||
sub r2, r2, #12
|
||||
PLD( subs r2, r2, #32 )
|
||||
PLD( blt 33f )
|
||||
PLD( pld [r1, #-32] )
|
||||
32: PLD( pld [r1, #-48] )
|
||||
33: mov r7, r3, push #8
|
||||
ldmdb r1!, {r3, r4, r5, r6}
|
||||
subs r2, r2, #16
|
||||
orr r7, r7, r6, pull #24
|
||||
mov r6, r6, push #8
|
||||
orr r6, r6, r5, pull #24
|
||||
mov r5, r5, push #8
|
||||
orr r5, r5, r4, pull #24
|
||||
mov r4, r4, push #8
|
||||
orr r4, r4, r3, pull #24
|
||||
stmdb r0!, {r4, r5, r6, r7}
|
||||
bge 32b
|
||||
PLD( cmn r2, #32 )
|
||||
PLD( bge 33b )
|
||||
PLD( add r2, r2, #32 )
|
||||
adds r2, r2, #12
|
||||
blt 35f
|
||||
34: mov ip, r3, push #8
|
||||
ldr r3, [r1, #-4]!
|
||||
subs r2, r2, #4
|
||||
orr ip, ip, r3, pull #24
|
||||
str ip, [r0, #-4]!
|
||||
bge 34b
|
||||
35: add r1, r1, #3
|
||||
b 29b
|
||||
|
||||
36: cmp r2, #12
|
||||
blt 39f
|
||||
PLD( pld [r1, #-16] )
|
||||
sub r2, r2, #12
|
||||
PLD( subs r2, r2, #32 )
|
||||
PLD( blt 38f )
|
||||
PLD( pld [r1, #-32] )
|
||||
37: PLD( pld [r1, #-48] )
|
||||
38: mov r7, r3, push #16
|
||||
ldmdb r1!, {r3, r4, r5, r6}
|
||||
subs r2, r2, #16
|
||||
orr r7, r7, r6, pull #16
|
||||
mov r6, r6, push #16
|
||||
orr r6, r6, r5, pull #16
|
||||
mov r5, r5, push #16
|
||||
orr r5, r5, r4, pull #16
|
||||
mov r4, r4, push #16
|
||||
orr r4, r4, r3, pull #16
|
||||
stmdb r0!, {r4, r5, r6, r7}
|
||||
bge 37b
|
||||
PLD( cmn r2, #32 )
|
||||
PLD( bge 38b )
|
||||
PLD( add r2, r2, #32 )
|
||||
adds r2, r2, #12
|
||||
blt 40f
|
||||
39: mov ip, r3, push #16
|
||||
ldr r3, [r1, #-4]!
|
||||
subs r2, r2, #4
|
||||
orr ip, ip, r3, pull #16
|
||||
str ip, [r0, #-4]!
|
||||
bge 39b
|
||||
40: add r1, r1, #2
|
||||
b 29b
|
||||
|
||||
41: cmp r2, #12
|
||||
blt 44f
|
||||
PLD( pld [r1, #-16] )
|
||||
sub r2, r2, #12
|
||||
PLD( subs r2, r2, #32 )
|
||||
PLD( blt 43f )
|
||||
PLD( pld [r1, #-32] )
|
||||
42: PLD( pld [r1, #-48] )
|
||||
43: mov r7, r3, push #24
|
||||
ldmdb r1!, {r3, r4, r5, r6}
|
||||
subs r2, r2, #16
|
||||
orr r7, r7, r6, pull #8
|
||||
mov r6, r6, push #24
|
||||
orr r6, r6, r5, pull #8
|
||||
mov r5, r5, push #24
|
||||
orr r5, r5, r4, pull #8
|
||||
mov r4, r4, push #24
|
||||
orr r4, r4, r3, pull #8
|
||||
stmdb r0!, {r4, r5, r6, r7}
|
||||
bge 42b
|
||||
PLD( cmn r2, #32 )
|
||||
PLD( bge 43b )
|
||||
PLD( add r2, r2, #32 )
|
||||
adds r2, r2, #12
|
||||
blt 45f
|
||||
44: mov ip, r3, push #24
|
||||
ldr r3, [r1, #-4]!
|
||||
subs r2, r2, #4
|
||||
orr ip, ip, r3, pull #8
|
||||
str ip, [r0, #-4]!
|
||||
bge 44b
|
||||
45: add r1, r1, #1
|
||||
b 29b
|
||||
#include "copy_template.S"
|
||||
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* linux/arch/arm/lib/memmove.S
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Sep 28, 2005
|
||||
* Copyright: (C) MontaVista Software Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
/*
|
||||
* This can be used to enable code to cacheline align the source pointer.
|
||||
* Experiments on tested architectures (StrongARM and XScale) didn't show
|
||||
* this a worthwhile thing to do. That might be different in the future.
|
||||
*/
|
||||
//#define CALGN(code...) code
|
||||
#define CALGN(code...)
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* Prototype: void *memmove(void *dest, const void *src, size_t n);
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* If the memory regions don't overlap, we simply branch to memcpy which is
|
||||
* normally a bit faster. Otherwise the copy is done going downwards. This
|
||||
* is a transposition of the code from copy_template.S but with the copy
|
||||
* occurring in the opposite direction.
|
||||
*/
|
||||
|
||||
ENTRY(memmove)
|
||||
|
||||
subs ip, r0, r1
|
||||
cmphi r2, ip
|
||||
bls memcpy
|
||||
|
||||
stmfd sp!, {r0, r4, lr}
|
||||
add r1, r1, r2
|
||||
add r0, r0, r2
|
||||
subs r2, r2, #4
|
||||
blt 8f
|
||||
ands ip, r0, #3
|
||||
PLD( pld [r1, #-4] )
|
||||
bne 9f
|
||||
ands ip, r1, #3
|
||||
bne 10f
|
||||
|
||||
1: subs r2, r2, #(28)
|
||||
stmfd sp!, {r5 - r8}
|
||||
blt 5f
|
||||
|
||||
CALGN( ands ip, r1, #31 )
|
||||
CALGN( sbcnes r4, ip, r2 ) @ C is always set here
|
||||
CALGN( bcs 2f )
|
||||
CALGN( adr r4, 6f )
|
||||
CALGN( subs r2, r2, ip ) @ C is set here
|
||||
CALGN( add pc, r4, ip )
|
||||
|
||||
PLD( pld [r1, #-4] )
|
||||
2: PLD( subs r2, r2, #96 )
|
||||
PLD( pld [r1, #-32] )
|
||||
PLD( blt 4f )
|
||||
PLD( pld [r1, #-64] )
|
||||
PLD( pld [r1, #-96] )
|
||||
|
||||
3: PLD( pld [r1, #-128] )
|
||||
4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
|
||||
subs r2, r2, #32
|
||||
stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
|
||||
bge 3b
|
||||
PLD( cmn r2, #96 )
|
||||
PLD( bge 4b )
|
||||
|
||||
5: ands ip, r2, #28
|
||||
rsb ip, ip, #32
|
||||
addne pc, pc, ip @ C is always clear here
|
||||
b 7f
|
||||
6: nop
|
||||
ldr r3, [r1, #-4]!
|
||||
ldr r4, [r1, #-4]!
|
||||
ldr r5, [r1, #-4]!
|
||||
ldr r6, [r1, #-4]!
|
||||
ldr r7, [r1, #-4]!
|
||||
ldr r8, [r1, #-4]!
|
||||
ldr lr, [r1, #-4]!
|
||||
|
||||
add pc, pc, ip
|
||||
nop
|
||||
nop
|
||||
str r3, [r0, #-4]!
|
||||
str r4, [r0, #-4]!
|
||||
str r5, [r0, #-4]!
|
||||
str r6, [r0, #-4]!
|
||||
str r7, [r0, #-4]!
|
||||
str r8, [r0, #-4]!
|
||||
str lr, [r0, #-4]!
|
||||
|
||||
CALGN( bcs 2b )
|
||||
|
||||
7: ldmfd sp!, {r5 - r8}
|
||||
|
||||
8: movs r2, r2, lsl #31
|
||||
ldrneb r3, [r1, #-1]!
|
||||
ldrcsb r4, [r1, #-1]!
|
||||
ldrcsb ip, [r1, #-1]
|
||||
strneb r3, [r0, #-1]!
|
||||
strcsb r4, [r0, #-1]!
|
||||
strcsb ip, [r0, #-1]
|
||||
ldmfd sp!, {r0, r4, pc}
|
||||
|
||||
9: cmp ip, #2
|
||||
ldrgtb r3, [r1, #-1]!
|
||||
ldrgeb r4, [r1, #-1]!
|
||||
ldrb lr, [r1, #-1]!
|
||||
strgtb r3, [r0, #-1]!
|
||||
strgeb r4, [r0, #-1]!
|
||||
subs r2, r2, ip
|
||||
strb lr, [r0, #-1]!
|
||||
blt 8b
|
||||
ands ip, r1, #3
|
||||
beq 1b
|
||||
|
||||
10: bic r1, r1, #3
|
||||
cmp ip, #2
|
||||
ldr r3, [r1, #0]
|
||||
beq 17f
|
||||
blt 18f
|
||||
|
||||
|
||||
.macro backward_copy_shift push pull
|
||||
|
||||
subs r2, r2, #28
|
||||
blt 14f
|
||||
|
||||
CALGN( ands ip, r1, #31 )
|
||||
CALGN( rsb ip, ip, #32 )
|
||||
CALGN( sbcnes r4, ip, r2 ) @ C is always set here
|
||||
CALGN( subcc r2, r2, ip )
|
||||
CALGN( bcc 15f )
|
||||
|
||||
11: stmfd sp!, {r5 - r9}
|
||||
|
||||
PLD( pld [r1, #-4] )
|
||||
PLD( subs r2, r2, #96 )
|
||||
PLD( pld [r1, #-32] )
|
||||
PLD( blt 13f )
|
||||
PLD( pld [r1, #-64] )
|
||||
PLD( pld [r1, #-96] )
|
||||
|
||||
12: PLD( pld [r1, #-128] )
|
||||
13: ldmdb r1!, {r7, r8, r9, ip}
|
||||
mov lr, r3, push #\push
|
||||
subs r2, r2, #32
|
||||
ldmdb r1!, {r3, r4, r5, r6}
|
||||
orr lr, lr, ip, pull #\pull
|
||||
mov ip, ip, push #\push
|
||||
orr ip, ip, r9, pull #\pull
|
||||
mov r9, r9, push #\push
|
||||
orr r9, r9, r8, pull #\pull
|
||||
mov r8, r8, push #\push
|
||||
orr r8, r8, r7, pull #\pull
|
||||
mov r7, r7, push #\push
|
||||
orr r7, r7, r6, pull #\pull
|
||||
mov r6, r6, push #\push
|
||||
orr r6, r6, r5, pull #\pull
|
||||
mov r5, r5, push #\push
|
||||
orr r5, r5, r4, pull #\pull
|
||||
mov r4, r4, push #\push
|
||||
orr r4, r4, r3, pull #\pull
|
||||
stmdb r0!, {r4 - r9, ip, lr}
|
||||
bge 12b
|
||||
PLD( cmn r2, #96 )
|
||||
PLD( bge 13b )
|
||||
|
||||
ldmfd sp!, {r5 - r9}
|
||||
|
||||
14: ands ip, r2, #28
|
||||
beq 16f
|
||||
|
||||
15: mov lr, r3, push #\push
|
||||
ldr r3, [r1, #-4]!
|
||||
subs ip, ip, #4
|
||||
orr lr, lr, r3, pull #\pull
|
||||
str lr, [r0, #-4]!
|
||||
bgt 15b
|
||||
CALGN( cmp r2, #0 )
|
||||
CALGN( bge 11b )
|
||||
|
||||
16: add r1, r1, #(\pull / 8)
|
||||
b 8b
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
backward_copy_shift push=8 pull=24
|
||||
|
||||
17: backward_copy_shift push=16 pull=16
|
||||
|
||||
18: backward_copy_shift push=24 pull=8
|
||||
|
|
@ -657,41 +657,3 @@ USER( ldrgtbt r3, [r1], #1) @ May fault
|
|||
LOADREGS(fd,sp!, {r4 - r7, pc})
|
||||
.previous
|
||||
|
||||
/* Prototype: int __arch_clear_user(void *addr, size_t sz)
|
||||
* Purpose : clear some user memory
|
||||
* Params : addr - user memory address to clear
|
||||
* : sz - number of bytes to clear
|
||||
* Returns : number of bytes NOT cleared
|
||||
*/
|
||||
ENTRY(__arch_clear_user)
|
||||
stmfd sp!, {r1, lr}
|
||||
mov r2, #0
|
||||
cmp r1, #4
|
||||
blt 2f
|
||||
ands ip, r0, #3
|
||||
beq 1f
|
||||
cmp ip, #2
|
||||
USER( strbt r2, [r0], #1)
|
||||
USER( strlebt r2, [r0], #1)
|
||||
USER( strltbt r2, [r0], #1)
|
||||
rsb ip, ip, #4
|
||||
sub r1, r1, ip @ 7 6 5 4 3 2 1
|
||||
1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
|
||||
USER( strplt r2, [r0], #4)
|
||||
USER( strplt r2, [r0], #4)
|
||||
bpl 1b
|
||||
adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
|
||||
USER( strplt r2, [r0], #4)
|
||||
2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
|
||||
USER( strnebt r2, [r0], #1)
|
||||
USER( strnebt r2, [r0], #1)
|
||||
tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
|
||||
USER( strnebt r2, [r0], #1)
|
||||
mov r0, #0
|
||||
LOADREGS(fd,sp!, {r1, pc})
|
||||
|
||||
.section .fixup,"ax"
|
||||
.align 0
|
||||
9001: LOADREGS(fd,sp!, {r0, pc})
|
||||
.previous
|
||||
|
||||
|
|
|
@ -251,9 +251,33 @@ static struct platform_device serial_device = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct resource am79c961_resources[] = {
|
||||
{
|
||||
.start = 0x220,
|
||||
.end = 0x238,
|
||||
.flags = IORESOURCE_IO,
|
||||
}, {
|
||||
.start = IRQ_EBSA110_ETHERNET,
|
||||
.end = IRQ_EBSA110_ETHERNET,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device am79c961_device = {
|
||||
.name = "am79c961",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(am79c961_resources),
|
||||
.resource = am79c961_resources,
|
||||
};
|
||||
|
||||
static struct platform_device *ebsa110_devices[] = {
|
||||
&serial_device,
|
||||
&am79c961_device,
|
||||
};
|
||||
|
||||
static int __init ebsa110_init(void)
|
||||
{
|
||||
return platform_device_register(&serial_device);
|
||||
return platform_add_devices(ebsa110_devices, ARRAY_SIZE(ebsa110_devices));
|
||||
}
|
||||
|
||||
arch_initcall(ebsa110_init);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
obj-y := core.o pci.o
|
||||
obj-y := core.o pci.o uengine.o
|
||||
obj-m :=
|
||||
obj-n :=
|
||||
obj- :=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* arch/arm/mach-ixp2000/common.c
|
||||
* arch/arm/mach-ixp2000/core.c
|
||||
*
|
||||
* Common routines used by all IXP2400/2800 based platforms.
|
||||
*
|
||||
|
@ -49,7 +49,6 @@ static unsigned long ixp2000_slowport_irq_flags;
|
|||
*************************************************************************/
|
||||
void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg *old_cfg)
|
||||
{
|
||||
|
||||
spin_lock_irqsave(&ixp2000_slowport_lock, ixp2000_slowport_irq_flags);
|
||||
|
||||
old_cfg->CCR = *IXP2000_SLOWPORT_CCR;
|
||||
|
@ -62,7 +61,7 @@ void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg
|
|||
ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, new_cfg->WTC);
|
||||
ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, new_cfg->RTC);
|
||||
ixp2000_reg_write(IXP2000_SLOWPORT_PCR, new_cfg->PCR);
|
||||
ixp2000_reg_write(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
|
||||
ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
|
||||
}
|
||||
|
||||
void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
|
||||
|
@ -71,7 +70,7 @@ void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
|
|||
ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, old_cfg->WTC);
|
||||
ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, old_cfg->RTC);
|
||||
ixp2000_reg_write(IXP2000_SLOWPORT_PCR, old_cfg->PCR);
|
||||
ixp2000_reg_write(IXP2000_SLOWPORT_ADC, old_cfg->ADC);
|
||||
ixp2000_reg_wrb(IXP2000_SLOWPORT_ADC, old_cfg->ADC);
|
||||
|
||||
spin_unlock_irqrestore(&ixp2000_slowport_lock,
|
||||
ixp2000_slowport_irq_flags);
|
||||
|
@ -145,7 +144,7 @@ void __init ixp2000_map_io(void)
|
|||
iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
|
||||
|
||||
/* Set slowport to 8-bit mode. */
|
||||
ixp2000_reg_write(IXP2000_SLOWPORT_FRM, 1);
|
||||
ixp2000_reg_wrb(IXP2000_SLOWPORT_FRM, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -209,7 +208,7 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
write_seqlock(&xtime_lock);
|
||||
|
||||
/* clear timer 1 */
|
||||
ixp2000_reg_write(IXP2000_T1_CLR, 1);
|
||||
ixp2000_reg_wrb(IXP2000_T1_CLR, 1);
|
||||
|
||||
while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
|
||||
timer_tick(regs);
|
||||
|
@ -252,12 +251,12 @@ void __init ixp2000_init_time(unsigned long tick_rate)
|
|||
|
||||
ixp2000_reg_write(IXP2000_T4_CLR, 0);
|
||||
ixp2000_reg_write(IXP2000_T4_CLD, -1);
|
||||
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
|
||||
ixp2000_reg_wrb(IXP2000_T4_CTL, (1 << 7));
|
||||
missing_jiffy_timer_csr = IXP2000_T4_CSR;
|
||||
} else {
|
||||
ixp2000_reg_write(IXP2000_T2_CLR, 0);
|
||||
ixp2000_reg_write(IXP2000_T2_CLD, -1);
|
||||
ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
|
||||
ixp2000_reg_wrb(IXP2000_T2_CTL, (1 << 7));
|
||||
missing_jiffy_timer_csr = IXP2000_T2_CSR;
|
||||
}
|
||||
next_jiffy_time = 0xffffffff;
|
||||
|
@ -279,7 +278,7 @@ static void update_gpio_int_csrs(void)
|
|||
ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
|
||||
ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
|
||||
ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
|
||||
ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
|
||||
ixp2000_reg_wrb(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
|
||||
}
|
||||
|
||||
void gpio_line_config(int line, int direction)
|
||||
|
@ -297,9 +296,9 @@ void gpio_line_config(int line, int direction)
|
|||
GPIO_IRQ_level_high &= ~(1 << line);
|
||||
update_gpio_int_csrs();
|
||||
|
||||
ixp2000_reg_write(IXP2000_GPIO_PDSR, 1 << line);
|
||||
ixp2000_reg_wrb(IXP2000_GPIO_PDSR, 1 << line);
|
||||
} else if (direction == GPIO_IN) {
|
||||
ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);
|
||||
ixp2000_reg_wrb(IXP2000_GPIO_PDCR, 1 << line);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
@ -365,12 +364,12 @@ static void ixp2000_GPIO_irq_mask_ack(unsigned int irq)
|
|||
|
||||
ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
|
||||
ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
|
||||
ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
|
||||
ixp2000_reg_wrb(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
|
||||
}
|
||||
|
||||
static void ixp2000_GPIO_irq_mask(unsigned int irq)
|
||||
{
|
||||
ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
|
||||
ixp2000_reg_wrb(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
|
||||
}
|
||||
|
||||
static void ixp2000_GPIO_irq_unmask(unsigned int irq)
|
||||
|
@ -389,9 +388,9 @@ static void ixp2000_pci_irq_mask(unsigned int irq)
|
|||
{
|
||||
unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
|
||||
if (irq == IRQ_IXP2000_PCIA)
|
||||
ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
|
||||
ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
|
||||
else if (irq == IRQ_IXP2000_PCIB)
|
||||
ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
|
||||
ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
|
||||
}
|
||||
|
||||
static void ixp2000_pci_irq_unmask(unsigned int irq)
|
||||
|
@ -411,7 +410,7 @@ static struct irqchip ixp2000_pci_irq_chip = {
|
|||
|
||||
static void ixp2000_irq_mask(unsigned int irq)
|
||||
{
|
||||
ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, (1 << irq));
|
||||
ixp2000_reg_wrb(IXP2000_IRQ_ENABLE_CLR, (1 << irq));
|
||||
}
|
||||
|
||||
static void ixp2000_irq_unmask(unsigned int irq)
|
||||
|
@ -443,7 +442,7 @@ void __init ixp2000_init_irq(void)
|
|||
ixp2000_reg_write(IXP2000_GPIO_INCR, -1);
|
||||
|
||||
/* clear PCI interrupt sources */
|
||||
ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, 0);
|
||||
ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, 0);
|
||||
|
||||
/*
|
||||
* Certain bits in the IRQ status register of the
|
||||
|
|
|
@ -63,6 +63,35 @@ static struct sys_timer enp2611_timer = {
|
|||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* ENP-2611 I/O
|
||||
*************************************************************************/
|
||||
static struct map_desc enp2611_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = ENP2611_CALEB_VIRT_BASE,
|
||||
.physical = ENP2611_CALEB_PHYS_BASE,
|
||||
.length = ENP2611_CALEB_SIZE,
|
||||
.type = MT_IXP2000_DEVICE
|
||||
}, {
|
||||
.virtual = ENP2611_PM3386_0_VIRT_BASE,
|
||||
.physical = ENP2611_PM3386_0_PHYS_BASE,
|
||||
.length = ENP2611_PM3386_0_SIZE,
|
||||
.type = MT_IXP2000_DEVICE
|
||||
}, {
|
||||
.virtual = ENP2611_PM3386_1_VIRT_BASE,
|
||||
.physical = ENP2611_PM3386_1_PHYS_BASE,
|
||||
.length = ENP2611_PM3386_1_SIZE,
|
||||
.type = MT_IXP2000_DEVICE
|
||||
}
|
||||
};
|
||||
|
||||
void __init enp2611_map_io(void)
|
||||
{
|
||||
ixp2000_map_io();
|
||||
iotable_init(enp2611_io_desc, ARRAY_SIZE(enp2611_io_desc));
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* ENP-2611 PCI
|
||||
*************************************************************************/
|
||||
|
@ -229,7 +258,7 @@ MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
|
|||
.phys_io = IXP2000_UART_PHYS_BASE,
|
||||
.io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
|
||||
.boot_params = 0x00000100,
|
||||
.map_io = ixp2000_map_io,
|
||||
.map_io = enp2611_map_io,
|
||||
.init_irq = ixp2000_init_irq,
|
||||
.timer = &enp2611_timer,
|
||||
.init_machine = enp2611_init_machine,
|
||||
|
|
|
@ -81,7 +81,7 @@ static void ixdp2x00_irq_mask(unsigned int irq)
|
|||
|
||||
dummy = *board_irq_mask;
|
||||
dummy |= IXP2000_BOARD_IRQ_MASK(irq);
|
||||
ixp2000_reg_write(board_irq_mask, dummy);
|
||||
ixp2000_reg_wrb(board_irq_mask, dummy);
|
||||
|
||||
#ifdef CONFIG_ARCH_IXDP2400
|
||||
if (machine_is_ixdp2400())
|
||||
|
@ -101,7 +101,7 @@ static void ixdp2x00_irq_unmask(unsigned int irq)
|
|||
|
||||
dummy = *board_irq_mask;
|
||||
dummy &= ~IXP2000_BOARD_IRQ_MASK(irq);
|
||||
ixp2000_reg_write(board_irq_mask, dummy);
|
||||
ixp2000_reg_wrb(board_irq_mask, dummy);
|
||||
|
||||
if (machine_is_ixdp2400())
|
||||
ixp2000_release_slowport(&old_cfg);
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
*************************************************************************/
|
||||
static void ixdp2x01_irq_mask(unsigned int irq)
|
||||
{
|
||||
ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG,
|
||||
ixp2000_reg_wrb(IXDP2X01_INT_MASK_SET_REG,
|
||||
IXP2000_BOARD_IRQ_MASK(irq));
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ void __init ixdp2x01_init_irq(void)
|
|||
|
||||
/* Mask all interrupts from CPLD, disable simulation */
|
||||
ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG, 0xffffffff);
|
||||
ixp2000_reg_write(IXDP2X01_INT_SIM_REG, 0);
|
||||
ixp2000_reg_wrb(IXDP2X01_INT_SIM_REG, 0);
|
||||
|
||||
for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
|
||||
if (irq & valid_irq_mask) {
|
||||
|
@ -299,7 +299,6 @@ struct hw_pci ixdp2x01_pci __initdata = {
|
|||
|
||||
int __init ixdp2x01_pci_init(void)
|
||||
{
|
||||
|
||||
pci_common_init(&ixdp2x01_pci);
|
||||
return 0;
|
||||
}
|
||||
|
@ -316,7 +315,7 @@ static struct flash_platform_data ixdp2x01_flash_platform_data = {
|
|||
|
||||
static unsigned long ixdp2x01_flash_bank_setup(unsigned long ofs)
|
||||
{
|
||||
ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG,
|
||||
ixp2000_reg_wrb(IXDP2X01_CPLD_FLASH_REG,
|
||||
((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN));
|
||||
return (ofs & IXDP2X01_FLASH_WINDOW_MASK);
|
||||
}
|
||||
|
@ -363,7 +362,7 @@ static struct platform_device *ixdp2x01_devices[] __initdata = {
|
|||
|
||||
static void __init ixdp2x01_init_machine(void)
|
||||
{
|
||||
ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG,
|
||||
ixp2000_reg_wrb(IXDP2X01_CPLD_FLASH_REG,
|
||||
(IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN));
|
||||
|
||||
ixdp2x01_flash_data.nr_banks =
|
||||
|
|
|
@ -148,7 +148,7 @@ int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_re
|
|||
local_irq_save(flags);
|
||||
temp = *(IXP2000_PCI_CONTROL);
|
||||
if (temp & ((1 << 8) | (1 << 5))) {
|
||||
ixp2000_reg_write(IXP2000_PCI_CONTROL, temp);
|
||||
ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp);
|
||||
}
|
||||
|
||||
temp = *(IXP2000_PCI_CMDSTAT);
|
||||
|
@ -178,8 +178,8 @@ clear_master_aborts(void)
|
|||
|
||||
local_irq_save(flags);
|
||||
temp = *(IXP2000_PCI_CONTROL);
|
||||
if (temp & ((1 << 8) | (1 << 5))) {
|
||||
ixp2000_reg_write(IXP2000_PCI_CONTROL, temp);
|
||||
if (temp & ((1 << 8) | (1 << 5))) {
|
||||
ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp);
|
||||
}
|
||||
|
||||
temp = *(IXP2000_PCI_CMDSTAT);
|
||||
|
|
|
@ -0,0 +1,474 @@
|
|||
/*
|
||||
* Generic library functions for the microengines found on the Intel
|
||||
* IXP2000 series of network processors.
|
||||
*
|
||||
* Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
* Dedicated to Marija Kulikova.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/arch/ixp2000-regs.h>
|
||||
#include <asm/arch/uengine.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define USTORE_ADDRESS 0x000
|
||||
#define USTORE_DATA_LOWER 0x004
|
||||
#define USTORE_DATA_UPPER 0x008
|
||||
#define CTX_ENABLES 0x018
|
||||
#define CC_ENABLE 0x01c
|
||||
#define CSR_CTX_POINTER 0x020
|
||||
#define INDIRECT_CTX_STS 0x040
|
||||
#define ACTIVE_CTX_STS 0x044
|
||||
#define INDIRECT_CTX_SIG_EVENTS 0x048
|
||||
#define INDIRECT_CTX_WAKEUP_EVENTS 0x050
|
||||
#define NN_PUT 0x080
|
||||
#define NN_GET 0x084
|
||||
#define TIMESTAMP_LOW 0x0c0
|
||||
#define TIMESTAMP_HIGH 0x0c4
|
||||
#define T_INDEX_BYTE_INDEX 0x0f4
|
||||
#define LOCAL_CSR_STATUS 0x180
|
||||
|
||||
u32 ixp2000_uengine_mask;
|
||||
|
||||
static void *ixp2000_uengine_csr_area(int uengine)
|
||||
{
|
||||
return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR
|
||||
* space means that the microengine we tried to access was also trying
|
||||
* to access its own CSR space on the same clock cycle as we did. When
|
||||
* this happens, we lose the arbitration process by default, and the
|
||||
* read or write we tried to do was not actually performed, so we try
|
||||
* again until it succeeds.
|
||||
*/
|
||||
u32 ixp2000_uengine_csr_read(int uengine, int offset)
|
||||
{
|
||||
void *uebase;
|
||||
u32 *local_csr_status;
|
||||
u32 *reg;
|
||||
u32 value;
|
||||
|
||||
uebase = ixp2000_uengine_csr_area(uengine);
|
||||
|
||||
local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
|
||||
reg = (u32 *)(uebase + offset);
|
||||
do {
|
||||
value = ixp2000_reg_read(reg);
|
||||
} while (ixp2000_reg_read(local_csr_status) & 1);
|
||||
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_csr_read);
|
||||
|
||||
void ixp2000_uengine_csr_write(int uengine, int offset, u32 value)
|
||||
{
|
||||
void *uebase;
|
||||
u32 *local_csr_status;
|
||||
u32 *reg;
|
||||
|
||||
uebase = ixp2000_uengine_csr_area(uengine);
|
||||
|
||||
local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
|
||||
reg = (u32 *)(uebase + offset);
|
||||
do {
|
||||
ixp2000_reg_write(reg, value);
|
||||
} while (ixp2000_reg_read(local_csr_status) & 1);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_csr_write);
|
||||
|
||||
void ixp2000_uengine_reset(u32 uengine_mask)
|
||||
{
|
||||
ixp2000_reg_write(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask);
|
||||
ixp2000_reg_write(IXP2000_RESET1, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_reset);
|
||||
|
||||
void ixp2000_uengine_set_mode(int uengine, u32 mode)
|
||||
{
|
||||
/*
|
||||
* CTL_STR_PAR_EN: unconditionally enable parity checking on
|
||||
* control store.
|
||||
*/
|
||||
mode |= 0x10000000;
|
||||
ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode);
|
||||
|
||||
/*
|
||||
* Enable updating of condition codes.
|
||||
*/
|
||||
ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000);
|
||||
|
||||
/*
|
||||
* Initialise other per-microengine registers.
|
||||
*/
|
||||
ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00);
|
||||
ixp2000_uengine_csr_write(uengine, NN_GET, 0x00);
|
||||
ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_set_mode);
|
||||
|
||||
static int make_even_parity(u32 x)
|
||||
{
|
||||
return hweight32(x) & 1;
|
||||
}
|
||||
|
||||
static void ustore_write(int uengine, u64 insn)
|
||||
{
|
||||
/*
|
||||
* Generate even parity for top and bottom 20 bits.
|
||||
*/
|
||||
insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41;
|
||||
insn |= (u64)make_even_parity(insn & 0x000fffff) << 40;
|
||||
|
||||
/*
|
||||
* Write to microstore. The second write auto-increments
|
||||
* the USTORE_ADDRESS index register.
|
||||
*/
|
||||
ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn);
|
||||
ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32));
|
||||
}
|
||||
|
||||
void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Start writing to microstore at address 0.
|
||||
*/
|
||||
ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000);
|
||||
for (i = 0; i < insns; i++) {
|
||||
u64 insn;
|
||||
|
||||
insn = (((u64)ucode[0]) << 32) |
|
||||
(((u64)ucode[1]) << 24) |
|
||||
(((u64)ucode[2]) << 16) |
|
||||
(((u64)ucode[3]) << 8) |
|
||||
((u64)ucode[4]);
|
||||
ucode += 5;
|
||||
|
||||
ustore_write(uengine, insn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pad with a few NOPs at the end (to avoid the microengine
|
||||
* aborting as it prefetches beyond the last instruction), unless
|
||||
* we run off the end of the instruction store first, at which
|
||||
* point the address register will wrap back to zero.
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 addr;
|
||||
|
||||
addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS);
|
||||
if (addr == 0x80000000)
|
||||
break;
|
||||
ustore_write(uengine, 0xf0000c0300ULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* End programming.
|
||||
*/
|
||||
ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_load_microcode);
|
||||
|
||||
void ixp2000_uengine_init_context(int uengine, int context, int pc)
|
||||
{
|
||||
/*
|
||||
* Select the right context for indirect access.
|
||||
*/
|
||||
ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context);
|
||||
|
||||
/*
|
||||
* Initialise signal masks to immediately go to Ready state.
|
||||
*/
|
||||
ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1);
|
||||
ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1);
|
||||
|
||||
/*
|
||||
* Set program counter.
|
||||
*/
|
||||
ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_init_context);
|
||||
|
||||
void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
/*
|
||||
* Enable the specified context to go to Executing state.
|
||||
*/
|
||||
mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
|
||||
mask |= ctx_mask << 8;
|
||||
ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_start_contexts);
|
||||
|
||||
void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
/*
|
||||
* Disable the Ready->Executing transition. Note that this
|
||||
* does not stop the context until it voluntarily yields.
|
||||
*/
|
||||
mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
|
||||
mask &= ~(ctx_mask << 8);
|
||||
ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_stop_contexts);
|
||||
|
||||
static int check_ixp_type(struct ixp2000_uengine_code *c)
|
||||
{
|
||||
u32 product_id;
|
||||
u32 rev;
|
||||
|
||||
product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID);
|
||||
if (((product_id >> 16) & 0x1f) != 0)
|
||||
return 0;
|
||||
|
||||
switch ((product_id >> 8) & 0xff) {
|
||||
case 0: /* IXP2800 */
|
||||
if (!(c->cpu_model_bitmask & 4))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 1: /* IXP2850 */
|
||||
if (!(c->cpu_model_bitmask & 8))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 2: /* IXP2400 */
|
||||
if (!(c->cpu_model_bitmask & 2))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
rev = product_id & 0xff;
|
||||
if (rev < c->cpu_min_revision || rev > c->cpu_max_revision)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b)
|
||||
{
|
||||
int offset;
|
||||
int i;
|
||||
|
||||
offset = 0;
|
||||
|
||||
for (i = 0; i < 128; i++) {
|
||||
u8 b3;
|
||||
u8 b2;
|
||||
u8 b1;
|
||||
u8 b0;
|
||||
|
||||
b3 = (gpr_a[i] >> 24) & 0xff;
|
||||
b2 = (gpr_a[i] >> 16) & 0xff;
|
||||
b1 = (gpr_a[i] >> 8) & 0xff;
|
||||
b0 = gpr_a[i] & 0xff;
|
||||
|
||||
// immed[@ai, (b1 << 8) | b0]
|
||||
// 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII
|
||||
ucode[offset++] = 0xf0;
|
||||
ucode[offset++] = (b1 >> 4);
|
||||
ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6);
|
||||
ucode[offset++] = (b0 << 2);
|
||||
ucode[offset++] = 0x80 | i;
|
||||
|
||||
// immed_w1[@ai, (b3 << 8) | b2]
|
||||
// 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII
|
||||
ucode[offset++] = 0xf4;
|
||||
ucode[offset++] = 0x40 | (b3 >> 4);
|
||||
ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6);
|
||||
ucode[offset++] = (b2 << 2);
|
||||
ucode[offset++] = 0x80 | i;
|
||||
}
|
||||
|
||||
for (i = 0; i < 128; i++) {
|
||||
u8 b3;
|
||||
u8 b2;
|
||||
u8 b1;
|
||||
u8 b0;
|
||||
|
||||
b3 = (gpr_b[i] >> 24) & 0xff;
|
||||
b2 = (gpr_b[i] >> 16) & 0xff;
|
||||
b1 = (gpr_b[i] >> 8) & 0xff;
|
||||
b0 = gpr_b[i] & 0xff;
|
||||
|
||||
// immed[@bi, (b1 << 8) | b0]
|
||||
// 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV
|
||||
ucode[offset++] = 0xf0;
|
||||
ucode[offset++] = (b1 >> 4);
|
||||
ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6);
|
||||
ucode[offset++] = (i << 2) | 0x03;
|
||||
ucode[offset++] = b0;
|
||||
|
||||
// immed_w1[@bi, (b3 << 8) | b2]
|
||||
// 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV
|
||||
ucode[offset++] = 0xf4;
|
||||
ucode[offset++] = 0x40 | (b3 >> 4);
|
||||
ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6);
|
||||
ucode[offset++] = (i << 2) | 0x03;
|
||||
ucode[offset++] = b2;
|
||||
}
|
||||
|
||||
// ctx_arb[kill]
|
||||
ucode[offset++] = 0xe0;
|
||||
ucode[offset++] = 0x00;
|
||||
ucode[offset++] = 0x01;
|
||||
ucode[offset++] = 0x00;
|
||||
ucode[offset++] = 0x00;
|
||||
}
|
||||
|
||||
static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c)
|
||||
{
|
||||
int per_ctx_regs;
|
||||
u32 *gpr_a;
|
||||
u32 *gpr_b;
|
||||
u8 *ucode;
|
||||
int i;
|
||||
|
||||
gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL);
|
||||
gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL);
|
||||
ucode = kmalloc(513 * 5, GFP_KERNEL);
|
||||
if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) {
|
||||
kfree(ucode);
|
||||
kfree(gpr_b);
|
||||
kfree(gpr_a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
per_ctx_regs = 16;
|
||||
if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS)
|
||||
per_ctx_regs = 32;
|
||||
|
||||
memset(gpr_a, 0, sizeof(gpr_a));
|
||||
memset(gpr_b, 0, sizeof(gpr_b));
|
||||
for (i = 0; i < 256; i++) {
|
||||
struct ixp2000_reg_value *r = c->initial_reg_values + i;
|
||||
u32 *bank;
|
||||
int inc;
|
||||
int j;
|
||||
|
||||
if (r->reg == -1)
|
||||
break;
|
||||
|
||||
bank = (r->reg & 0x400) ? gpr_b : gpr_a;
|
||||
inc = (r->reg & 0x80) ? 128 : per_ctx_regs;
|
||||
|
||||
j = r->reg & 0x7f;
|
||||
while (j < 128) {
|
||||
bank[j] = r->value;
|
||||
j += inc;
|
||||
}
|
||||
}
|
||||
|
||||
generate_ucode(ucode, gpr_a, gpr_b);
|
||||
ixp2000_uengine_load_microcode(uengine, ucode, 513);
|
||||
ixp2000_uengine_init_context(uengine, 0, 0);
|
||||
ixp2000_uengine_start_contexts(uengine, 0x01);
|
||||
for (i = 0; i < 100; i++) {
|
||||
u32 status;
|
||||
|
||||
status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS);
|
||||
if (!(status & 0x80000000))
|
||||
break;
|
||||
}
|
||||
ixp2000_uengine_stop_contexts(uengine, 0x01);
|
||||
|
||||
kfree(ucode);
|
||||
kfree(gpr_b);
|
||||
kfree(gpr_a);
|
||||
|
||||
return !!(i == 100);
|
||||
}
|
||||
|
||||
int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c)
|
||||
{
|
||||
int ctx;
|
||||
|
||||
if (!check_ixp_type(c))
|
||||
return 1;
|
||||
|
||||
if (!(ixp2000_uengine_mask & (1 << uengine)))
|
||||
return 1;
|
||||
|
||||
ixp2000_uengine_reset(1 << uengine);
|
||||
ixp2000_uengine_set_mode(uengine, c->uengine_parameters);
|
||||
if (set_initial_registers(uengine, c))
|
||||
return 1;
|
||||
ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns);
|
||||
|
||||
for (ctx = 0; ctx < 8; ctx++)
|
||||
ixp2000_uengine_init_context(uengine, ctx, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ixp2000_uengine_load);
|
||||
|
||||
|
||||
static int __init ixp2000_uengine_init(void)
|
||||
{
|
||||
int uengine;
|
||||
u32 value;
|
||||
|
||||
/*
|
||||
* Determine number of microengines present.
|
||||
*/
|
||||
switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) {
|
||||
case 0: /* IXP2800 */
|
||||
case 1: /* IXP2850 */
|
||||
ixp2000_uengine_mask = 0x00ff00ff;
|
||||
break;
|
||||
|
||||
case 2: /* IXP2400 */
|
||||
ixp2000_uengine_mask = 0x000f000f;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n",
|
||||
(unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID));
|
||||
ixp2000_uengine_mask = 0x00000000;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset microengines.
|
||||
*/
|
||||
ixp2000_reg_write(IXP2000_RESET1, ixp2000_uengine_mask);
|
||||
ixp2000_reg_write(IXP2000_RESET1, 0);
|
||||
|
||||
/*
|
||||
* Synchronise timestamp counters across all microengines.
|
||||
*/
|
||||
value = ixp2000_reg_read(IXP2000_MISC_CONTROL);
|
||||
ixp2000_reg_write(IXP2000_MISC_CONTROL, value & ~0x80);
|
||||
for (uengine = 0; uengine < 32; uengine++) {
|
||||
if (ixp2000_uengine_mask & (1 << uengine)) {
|
||||
ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
|
||||
ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
|
||||
}
|
||||
}
|
||||
ixp2000_reg_write(IXP2000_MISC_CONTROL, value | 0x80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(ixp2000_uengine_init);
|
|
@ -175,7 +175,7 @@ static struct platform_device sa1111_device = {
|
|||
static struct resource smc91x_resources[] = {
|
||||
[0] = {
|
||||
.name = "smc91x-regs",
|
||||
.start = 0x0c000000,
|
||||
.start = 0x0c000c00,
|
||||
.end = 0x0c0fffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
|
@ -224,18 +224,75 @@ static struct pxafb_mach_info sharp_lm8v31 __initdata = {
|
|||
.lccr3 = LCCR3_PCP | LCCR3_Acb(255),
|
||||
};
|
||||
|
||||
static int lubbock_mci_init(struct device *dev, irqreturn_t (*lubbock_detect_int)(int, void *, struct pt_regs *), void *data)
|
||||
#define MMC_POLL_RATE msecs_to_jiffies(1000)
|
||||
|
||||
static void lubbock_mmc_poll(unsigned long);
|
||||
static irqreturn_t (*mmc_detect_int)(int, void *, struct pt_regs *);
|
||||
|
||||
static struct timer_list mmc_timer = {
|
||||
.function = lubbock_mmc_poll,
|
||||
};
|
||||
|
||||
static void lubbock_mmc_poll(unsigned long data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* clear any previous irq state, then ... */
|
||||
local_irq_save(flags);
|
||||
LUB_IRQ_SET_CLR &= ~(1 << 0);
|
||||
local_irq_restore(flags);
|
||||
|
||||
/* poll until mmc/sd card is removed */
|
||||
if (LUB_IRQ_SET_CLR & (1 << 0))
|
||||
mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE);
|
||||
else {
|
||||
(void) mmc_detect_int(LUBBOCK_SD_IRQ, (void *)data, NULL);
|
||||
enable_irq(LUBBOCK_SD_IRQ);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t lubbock_detect_int(int irq, void *data, struct pt_regs *regs)
|
||||
{
|
||||
/* IRQ is level triggered; disable, and poll for removal */
|
||||
disable_irq(irq);
|
||||
mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE);
|
||||
|
||||
return mmc_detect_int(irq, data, regs);
|
||||
}
|
||||
|
||||
static int lubbock_mci_init(struct device *dev,
|
||||
irqreturn_t (*detect_int)(int, void *, struct pt_regs *),
|
||||
void *data)
|
||||
{
|
||||
/* setup GPIO for PXA25x MMC controller */
|
||||
pxa_gpio_mode(GPIO6_MMCCLK_MD);
|
||||
pxa_gpio_mode(GPIO8_MMCCS0_MD);
|
||||
|
||||
return 0;
|
||||
/* detect card insert/eject */
|
||||
mmc_detect_int = detect_int;
|
||||
init_timer(&mmc_timer);
|
||||
mmc_timer.data = (unsigned long) data;
|
||||
return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int,
|
||||
SA_SAMPLE_RANDOM, "lubbock-sd-detect", data);
|
||||
}
|
||||
|
||||
static int lubbock_mci_get_ro(struct device *dev)
|
||||
{
|
||||
return (LUB_MISC_RD & (1 << 2)) != 0;
|
||||
}
|
||||
|
||||
static void lubbock_mci_exit(struct device *dev, void *data)
|
||||
{
|
||||
free_irq(LUBBOCK_SD_IRQ, data);
|
||||
del_timer_sync(&mmc_timer);
|
||||
}
|
||||
|
||||
static struct pxamci_platform_data lubbock_mci_platform_data = {
|
||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||
.detect_delay = 1,
|
||||
.init = lubbock_mci_init,
|
||||
.get_ro = lubbock_mci_get_ro,
|
||||
.exit = lubbock_mci_exit,
|
||||
};
|
||||
|
||||
static void lubbock_irda_transceiver_mode(struct device *dev, int mode)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
menu "RealView platform type"
|
||||
depends on ARCH_REALVIEW
|
||||
|
||||
config MACH_REALVIEW_EB
|
||||
bool "Support RealView/EB platform"
|
||||
default n
|
||||
select ARM_GIC
|
||||
help
|
||||
Include support for the ARM(R) RealView Emulation Baseboard platform.
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
obj-y := core.o clock.o
|
||||
obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
|
|
@ -0,0 +1,4 @@
|
|||
zreladdr-y := 0x00008000
|
||||
params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x00800000
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-realview/clock.c
|
||||
*
|
||||
* Copyright (C) 2004 ARM Limited.
|
||||
* Written by Deep Blue Solutions Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/hardware/clock.h>
|
||||
#include <asm/hardware/icst307.h>
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
static LIST_HEAD(clocks);
|
||||
static DECLARE_MUTEX(clocks_sem);
|
||||
|
||||
struct clk *clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
struct clk *p, *clk = ERR_PTR(-ENOENT);
|
||||
|
||||
down(&clocks_sem);
|
||||
list_for_each_entry(p, &clocks, node) {
|
||||
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
|
||||
clk = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&clocks_sem);
|
||||
|
||||
return clk;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get);
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
module_put(clk->owner);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_put);
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_enable);
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
int clk_use(struct clk *clk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_use);
|
||||
|
||||
void clk_unuse(struct clk *clk)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(clk_unuse);
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
return clk->rate;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
|
||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return rate;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_round_rate);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
int ret = -EIO;
|
||||
|
||||
if (clk->setvco) {
|
||||
struct icst307_vco vco;
|
||||
|
||||
vco = icst307_khz_to_vco(clk->params, rate / 1000);
|
||||
clk->rate = icst307_khz(clk->params, vco) * 1000;
|
||||
|
||||
printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
|
||||
clk->name, vco.s, vco.r, vco.v);
|
||||
|
||||
clk->setvco(clk, vco);
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_rate);
|
||||
|
||||
/*
|
||||
* These are fixed clocks.
|
||||
*/
|
||||
static struct clk kmi_clk = {
|
||||
.name = "KMIREFCLK",
|
||||
.rate = 24000000,
|
||||
};
|
||||
|
||||
static struct clk uart_clk = {
|
||||
.name = "UARTCLK",
|
||||
.rate = 24000000,
|
||||
};
|
||||
|
||||
static struct clk mmci_clk = {
|
||||
.name = "MCLK",
|
||||
.rate = 33000000,
|
||||
};
|
||||
|
||||
int clk_register(struct clk *clk)
|
||||
{
|
||||
down(&clocks_sem);
|
||||
list_add(&clk->node, &clocks);
|
||||
up(&clocks_sem);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_register);
|
||||
|
||||
void clk_unregister(struct clk *clk)
|
||||
{
|
||||
down(&clocks_sem);
|
||||
list_del(&clk->node);
|
||||
up(&clocks_sem);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_unregister);
|
||||
|
||||
static int __init clk_init(void)
|
||||
{
|
||||
clk_register(&kmi_clk);
|
||||
clk_register(&uart_clk);
|
||||
clk_register(&mmci_clk);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(clk_init);
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-realview/clock.h
|
||||
*
|
||||
* Copyright (C) 2004 ARM Limited.
|
||||
* Written by Deep Blue Solutions Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
struct module;
|
||||
struct icst307_params;
|
||||
|
||||
struct clk {
|
||||
struct list_head node;
|
||||
unsigned long rate;
|
||||
struct module *owner;
|
||||
const char *name;
|
||||
const struct icst307_params *params;
|
||||
void *data;
|
||||
void (*setvco)(struct clk *, struct icst307_vco vco);
|
||||
};
|
||||
|
||||
int clk_register(struct clk *clk);
|
||||
void clk_unregister(struct clk *clk);
|
|
@ -0,0 +1,605 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-realview/core.c
|
||||
*
|
||||
* Copyright (C) 1999 - 2003 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/leds.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware/amba.h>
|
||||
#include <asm/hardware/amba_clcd.h>
|
||||
#include <asm/hardware/arm_timer.h>
|
||||
#include <asm/hardware/icst307.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/mmc.h>
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "clock.h"
|
||||
|
||||
#define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
|
||||
|
||||
/*
|
||||
* This is the RealView sched_clock implementation. This has
|
||||
* a resolution of 41.7ns, and a maximum value of about 179s.
|
||||
*/
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
unsigned long long v;
|
||||
|
||||
v = (unsigned long long)readl(REALVIEW_REFCOUNTER) * 125;
|
||||
do_div(v, 3);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
#define REALVIEW_FLASHCTRL (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_FLASH_OFFSET)
|
||||
|
||||
static int realview_flash_init(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = __raw_readl(REALVIEW_FLASHCTRL);
|
||||
val &= ~REALVIEW_FLASHPROG_FLVPPEN;
|
||||
__raw_writel(val, REALVIEW_FLASHCTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void realview_flash_exit(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = __raw_readl(REALVIEW_FLASHCTRL);
|
||||
val &= ~REALVIEW_FLASHPROG_FLVPPEN;
|
||||
__raw_writel(val, REALVIEW_FLASHCTRL);
|
||||
}
|
||||
|
||||
static void realview_flash_set_vpp(int on)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = __raw_readl(REALVIEW_FLASHCTRL);
|
||||
if (on)
|
||||
val |= REALVIEW_FLASHPROG_FLVPPEN;
|
||||
else
|
||||
val &= ~REALVIEW_FLASHPROG_FLVPPEN;
|
||||
__raw_writel(val, REALVIEW_FLASHCTRL);
|
||||
}
|
||||
|
||||
static struct flash_platform_data realview_flash_data = {
|
||||
.map_name = "cfi_probe",
|
||||
.width = 4,
|
||||
.init = realview_flash_init,
|
||||
.exit = realview_flash_exit,
|
||||
.set_vpp = realview_flash_set_vpp,
|
||||
};
|
||||
|
||||
static struct resource realview_flash_resource = {
|
||||
.start = REALVIEW_FLASH_BASE,
|
||||
.end = REALVIEW_FLASH_BASE + REALVIEW_FLASH_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
struct platform_device realview_flash_device = {
|
||||
.name = "armflash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &realview_flash_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &realview_flash_resource,
|
||||
};
|
||||
|
||||
static struct resource realview_smc91x_resources[] = {
|
||||
[0] = {
|
||||
.start = REALVIEW_ETH_BASE,
|
||||
.end = REALVIEW_ETH_BASE + SZ_64K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_ETH,
|
||||
.end = IRQ_ETH,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device realview_smc91x_device = {
|
||||
.name = "smc91x",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(realview_smc91x_resources),
|
||||
.resource = realview_smc91x_resources,
|
||||
};
|
||||
|
||||
#define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
|
||||
|
||||
static unsigned int realview_mmc_status(struct device *dev)
|
||||
{
|
||||
struct amba_device *adev = container_of(dev, struct amba_device, dev);
|
||||
u32 mask;
|
||||
|
||||
if (adev->res.start == REALVIEW_MMCI0_BASE)
|
||||
mask = 1;
|
||||
else
|
||||
mask = 2;
|
||||
|
||||
return readl(REALVIEW_SYSMCI) & mask;
|
||||
}
|
||||
|
||||
struct mmc_platform_data realview_mmc0_plat_data = {
|
||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||
.status = realview_mmc_status,
|
||||
};
|
||||
|
||||
struct mmc_platform_data realview_mmc1_plat_data = {
|
||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||
.status = realview_mmc_status,
|
||||
};
|
||||
|
||||
/*
|
||||
* Clock handling
|
||||
*/
|
||||
static const struct icst307_params realview_oscvco_params = {
|
||||
.ref = 24000,
|
||||
.vco_max = 200000,
|
||||
.vd_min = 4 + 8,
|
||||
.vd_max = 511 + 8,
|
||||
.rd_min = 1 + 2,
|
||||
.rd_max = 127 + 2,
|
||||
};
|
||||
|
||||
static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco)
|
||||
{
|
||||
void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET;
|
||||
void __iomem *sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC1_OFFSET;
|
||||
u32 val;
|
||||
|
||||
val = readl(sys_osc) & ~0x7ffff;
|
||||
val |= vco.v | (vco.r << 9) | (vco.s << 16);
|
||||
|
||||
writel(0xa05f, sys_lock);
|
||||
writel(val, sys_osc);
|
||||
writel(0, sys_lock);
|
||||
}
|
||||
|
||||
struct clk realview_clcd_clk = {
|
||||
.name = "CLCDCLK",
|
||||
.params = &realview_oscvco_params,
|
||||
.setvco = realview_oscvco_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* CLCD support.
|
||||
*/
|
||||
#define SYS_CLCD_MODE_MASK (3 << 0)
|
||||
#define SYS_CLCD_MODE_888 (0 << 0)
|
||||
#define SYS_CLCD_MODE_5551 (1 << 0)
|
||||
#define SYS_CLCD_MODE_565_RLSB (2 << 0)
|
||||
#define SYS_CLCD_MODE_565_BLSB (3 << 0)
|
||||
#define SYS_CLCD_NLCDIOON (1 << 2)
|
||||
#define SYS_CLCD_VDDPOSSWITCH (1 << 3)
|
||||
#define SYS_CLCD_PWR3V5SWITCH (1 << 4)
|
||||
#define SYS_CLCD_ID_MASK (0x1f << 8)
|
||||
#define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8)
|
||||
#define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8)
|
||||
#define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8)
|
||||
#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8)
|
||||
#define SYS_CLCD_ID_VGA (0x1f << 8)
|
||||
|
||||
static struct clcd_panel vga = {
|
||||
.mode = {
|
||||
.name = "VGA",
|
||||
.refresh = 60,
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.pixclock = 39721,
|
||||
.left_margin = 40,
|
||||
.right_margin = 24,
|
||||
.upper_margin = 32,
|
||||
.lower_margin = 11,
|
||||
.hsync_len = 96,
|
||||
.vsync_len = 2,
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = TIM2_BCD | TIM2_IPC,
|
||||
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
|
||||
.bpp = 16,
|
||||
};
|
||||
|
||||
static struct clcd_panel sanyo_3_8_in = {
|
||||
.mode = {
|
||||
.name = "Sanyo QVGA",
|
||||
.refresh = 116,
|
||||
.xres = 320,
|
||||
.yres = 240,
|
||||
.pixclock = 100000,
|
||||
.left_margin = 6,
|
||||
.right_margin = 6,
|
||||
.upper_margin = 5,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 6,
|
||||
.vsync_len = 6,
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = TIM2_BCD,
|
||||
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
|
||||
.bpp = 16,
|
||||
};
|
||||
|
||||
static struct clcd_panel sanyo_2_5_in = {
|
||||
.mode = {
|
||||
.name = "Sanyo QVGA Portrait",
|
||||
.refresh = 116,
|
||||
.xres = 240,
|
||||
.yres = 320,
|
||||
.pixclock = 100000,
|
||||
.left_margin = 20,
|
||||
.right_margin = 10,
|
||||
.upper_margin = 2,
|
||||
.lower_margin = 2,
|
||||
.hsync_len = 10,
|
||||
.vsync_len = 2,
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC,
|
||||
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
|
||||
.bpp = 16,
|
||||
};
|
||||
|
||||
static struct clcd_panel epson_2_2_in = {
|
||||
.mode = {
|
||||
.name = "Epson QCIF",
|
||||
.refresh = 390,
|
||||
.xres = 176,
|
||||
.yres = 220,
|
||||
.pixclock = 62500,
|
||||
.left_margin = 3,
|
||||
.right_margin = 2,
|
||||
.upper_margin = 1,
|
||||
.lower_margin = 0,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 2,
|
||||
.sync = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = TIM2_BCD | TIM2_IPC,
|
||||
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
|
||||
.bpp = 16,
|
||||
};
|
||||
|
||||
/*
|
||||
* Detect which LCD panel is connected, and return the appropriate
|
||||
* clcd_panel structure. Note: we do not have any information on
|
||||
* the required timings for the 8.4in panel, so we presently assume
|
||||
* VGA timings.
|
||||
*/
|
||||
static struct clcd_panel *realview_clcd_panel(void)
|
||||
{
|
||||
void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
|
||||
struct clcd_panel *panel = &vga;
|
||||
u32 val;
|
||||
|
||||
val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
|
||||
if (val == SYS_CLCD_ID_SANYO_3_8)
|
||||
panel = &sanyo_3_8_in;
|
||||
else if (val == SYS_CLCD_ID_SANYO_2_5)
|
||||
panel = &sanyo_2_5_in;
|
||||
else if (val == SYS_CLCD_ID_EPSON_2_2)
|
||||
panel = &epson_2_2_in;
|
||||
else if (val == SYS_CLCD_ID_VGA)
|
||||
panel = &vga;
|
||||
else {
|
||||
printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
|
||||
val);
|
||||
panel = &vga;
|
||||
}
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable all display connectors on the interface module.
|
||||
*/
|
||||
static void realview_clcd_disable(struct clcd_fb *fb)
|
||||
{
|
||||
void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
|
||||
u32 val;
|
||||
|
||||
val = readl(sys_clcd);
|
||||
val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
|
||||
writel(val, sys_clcd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the relevant connector on the interface module.
|
||||
*/
|
||||
static void realview_clcd_enable(struct clcd_fb *fb)
|
||||
{
|
||||
void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
|
||||
u32 val;
|
||||
|
||||
val = readl(sys_clcd);
|
||||
val &= ~SYS_CLCD_MODE_MASK;
|
||||
|
||||
switch (fb->fb.var.green.length) {
|
||||
case 5:
|
||||
val |= SYS_CLCD_MODE_5551;
|
||||
break;
|
||||
case 6:
|
||||
val |= SYS_CLCD_MODE_565_RLSB;
|
||||
break;
|
||||
case 8:
|
||||
val |= SYS_CLCD_MODE_888;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the MUX
|
||||
*/
|
||||
writel(val, sys_clcd);
|
||||
|
||||
/*
|
||||
* And now enable the PSUs
|
||||
*/
|
||||
val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
|
||||
writel(val, sys_clcd);
|
||||
}
|
||||
|
||||
static unsigned long framesize = SZ_1M;
|
||||
|
||||
static int realview_clcd_setup(struct clcd_fb *fb)
|
||||
{
|
||||
dma_addr_t dma;
|
||||
|
||||
fb->panel = realview_clcd_panel();
|
||||
|
||||
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
|
||||
&dma, GFP_KERNEL);
|
||||
if (!fb->fb.screen_base) {
|
||||
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
fb->fb.fix.smem_start = dma;
|
||||
fb->fb.fix.smem_len = framesize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int realview_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
|
||||
{
|
||||
return dma_mmap_writecombine(&fb->dev->dev, vma,
|
||||
fb->fb.screen_base,
|
||||
fb->fb.fix.smem_start,
|
||||
fb->fb.fix.smem_len);
|
||||
}
|
||||
|
||||
static void realview_clcd_remove(struct clcd_fb *fb)
|
||||
{
|
||||
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
|
||||
fb->fb.screen_base, fb->fb.fix.smem_start);
|
||||
}
|
||||
|
||||
struct clcd_board clcd_plat_data = {
|
||||
.name = "RealView",
|
||||
.check = clcdfb_check,
|
||||
.decode = clcdfb_decode,
|
||||
.disable = realview_clcd_disable,
|
||||
.enable = realview_clcd_enable,
|
||||
.setup = realview_clcd_setup,
|
||||
.mmap = realview_clcd_mmap,
|
||||
.remove = realview_clcd_remove,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LEDS
|
||||
#define VA_LEDS_BASE (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET)
|
||||
|
||||
void realview_leds_event(led_event_t ledevt)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
local_irq_save(flags);
|
||||
val = readl(VA_LEDS_BASE);
|
||||
|
||||
switch (ledevt) {
|
||||
case led_idle_start:
|
||||
val = val & ~REALVIEW_SYS_LED0;
|
||||
break;
|
||||
|
||||
case led_idle_end:
|
||||
val = val | REALVIEW_SYS_LED0;
|
||||
break;
|
||||
|
||||
case led_timer:
|
||||
val = val ^ REALVIEW_SYS_LED1;
|
||||
break;
|
||||
|
||||
case led_halted:
|
||||
val = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
writel(val, VA_LEDS_BASE);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
#endif /* CONFIG_LEDS */
|
||||
|
||||
/*
|
||||
* Where is the timer (VA)?
|
||||
*/
|
||||
#define TIMER0_VA_BASE __io_address(REALVIEW_TIMER0_1_BASE)
|
||||
#define TIMER1_VA_BASE (__io_address(REALVIEW_TIMER0_1_BASE) + 0x20)
|
||||
#define TIMER2_VA_BASE __io_address(REALVIEW_TIMER2_3_BASE)
|
||||
#define TIMER3_VA_BASE (__io_address(REALVIEW_TIMER2_3_BASE) + 0x20)
|
||||
|
||||
/*
|
||||
* How long is the timer interval?
|
||||
*/
|
||||
#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
|
||||
#if TIMER_INTERVAL >= 0x100000
|
||||
#define TIMER_RELOAD (TIMER_INTERVAL >> 8)
|
||||
#define TIMER_DIVISOR (TIMER_CTRL_DIV256)
|
||||
#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
|
||||
#elif TIMER_INTERVAL >= 0x10000
|
||||
#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */
|
||||
#define TIMER_DIVISOR (TIMER_CTRL_DIV16)
|
||||
#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
|
||||
#else
|
||||
#define TIMER_RELOAD (TIMER_INTERVAL)
|
||||
#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
|
||||
#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns number of ms since last clock interrupt. Note that interrupts
|
||||
* will have been disabled by do_gettimeoffset()
|
||||
*/
|
||||
static unsigned long realview_gettimeoffset(void)
|
||||
{
|
||||
unsigned long ticks1, ticks2, status;
|
||||
|
||||
/*
|
||||
* Get the current number of ticks. Note that there is a race
|
||||
* condition between us reading the timer and checking for
|
||||
* an interrupt. We get around this by ensuring that the
|
||||
* counter has not reloaded between our two reads.
|
||||
*/
|
||||
ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
|
||||
do {
|
||||
ticks1 = ticks2;
|
||||
status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET)
|
||||
+ ((IRQ_TIMERINT0_1 >> 5) << 2));
|
||||
ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
|
||||
} while (ticks2 > ticks1);
|
||||
|
||||
/*
|
||||
* Number of ticks since last interrupt.
|
||||
*/
|
||||
ticks1 = TIMER_RELOAD - ticks2;
|
||||
|
||||
/*
|
||||
* Interrupt pending? If so, we've reloaded once already.
|
||||
*
|
||||
* FIXME: Need to check this is effectively timer 0 that expires
|
||||
*/
|
||||
if (status & IRQMASK_TIMERINT0_1)
|
||||
ticks1 += TIMER_RELOAD;
|
||||
|
||||
/*
|
||||
* Convert the ticks to usecs
|
||||
*/
|
||||
return TICKS2USECS(ticks1);
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handler for the timer
|
||||
*/
|
||||
static irqreturn_t realview_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
// ...clear the interrupt
|
||||
writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
|
||||
|
||||
timer_tick(regs);
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction realview_timer_irq = {
|
||||
.name = "RealView Timer Tick",
|
||||
.flags = SA_INTERRUPT | SA_TIMER,
|
||||
.handler = realview_timer_interrupt,
|
||||
};
|
||||
|
||||
/*
|
||||
* Set up timer interrupt, and return the current time in seconds.
|
||||
*/
|
||||
static void __init realview_timer_init(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* set clock frequency:
|
||||
* REALVIEW_REFCLK is 32KHz
|
||||
* REALVIEW_TIMCLK is 1MHz
|
||||
*/
|
||||
val = readl(__io_address(REALVIEW_SCTL_BASE));
|
||||
writel((REALVIEW_TIMCLK << REALVIEW_TIMER1_EnSel) |
|
||||
(REALVIEW_TIMCLK << REALVIEW_TIMER2_EnSel) |
|
||||
(REALVIEW_TIMCLK << REALVIEW_TIMER3_EnSel) |
|
||||
(REALVIEW_TIMCLK << REALVIEW_TIMER4_EnSel) | val,
|
||||
__io_address(REALVIEW_SCTL_BASE));
|
||||
|
||||
/*
|
||||
* Initialise to a known state (all timers off)
|
||||
*/
|
||||
writel(0, TIMER0_VA_BASE + TIMER_CTRL);
|
||||
writel(0, TIMER1_VA_BASE + TIMER_CTRL);
|
||||
writel(0, TIMER2_VA_BASE + TIMER_CTRL);
|
||||
writel(0, TIMER3_VA_BASE + TIMER_CTRL);
|
||||
|
||||
writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
|
||||
writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
|
||||
writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
|
||||
TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
|
||||
|
||||
/*
|
||||
* Make irqs happen for the system timer
|
||||
*/
|
||||
setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq);
|
||||
}
|
||||
|
||||
struct sys_timer realview_timer = {
|
||||
.init = realview_timer_init,
|
||||
.offset = realview_gettimeoffset,
|
||||
};
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-realview/core.h
|
||||
*
|
||||
* Copyright (C) 2004 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_REALVIEW_H
|
||||
#define __ASM_ARCH_REALVIEW_H
|
||||
|
||||
#include <asm/hardware/amba.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define __io_address(n) __io(IO_ADDRESS(n))
|
||||
|
||||
extern struct sys_timer realview_timer;
|
||||
|
||||
#define AMBA_DEVICE(name,busid,base,plat) \
|
||||
static struct amba_device name##_device = { \
|
||||
.dev = { \
|
||||
.coherent_dma_mask = ~0, \
|
||||
.bus_id = busid, \
|
||||
.platform_data = plat, \
|
||||
}, \
|
||||
.res = { \
|
||||
.start = REALVIEW_##base##_BASE, \
|
||||
.end = (REALVIEW_##base##_BASE) + SZ_4K - 1,\
|
||||
.flags = IORESOURCE_MEM, \
|
||||
}, \
|
||||
.dma_mask = ~0, \
|
||||
.irq = base##_IRQ, \
|
||||
/* .dma = base##_DMA,*/ \
|
||||
}
|
||||
|
||||
/*
|
||||
* These devices are connected via the core APB bridge
|
||||
*/
|
||||
#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ }
|
||||
#define GPIO2_DMA { 0, 0 }
|
||||
#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ }
|
||||
#define GPIO3_DMA { 0, 0 }
|
||||
|
||||
#define AACI_IRQ { IRQ_AACI, NO_IRQ }
|
||||
#define AACI_DMA { 0x80, 0x81 }
|
||||
#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_MMCI0B }
|
||||
#define MMCI0_DMA { 0x84, 0 }
|
||||
#define KMI0_IRQ { IRQ_KMI0, NO_IRQ }
|
||||
#define KMI0_DMA { 0, 0 }
|
||||
#define KMI1_IRQ { IRQ_KMI1, NO_IRQ }
|
||||
#define KMI1_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected directly to the multi-layer AHB switch
|
||||
*/
|
||||
#define SMC_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define SMC_DMA { 0, 0 }
|
||||
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define MPMC_DMA { 0, 0 }
|
||||
#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ }
|
||||
#define CLCD_DMA { 0, 0 }
|
||||
#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ }
|
||||
#define DMAC_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected via the core APB bridge
|
||||
*/
|
||||
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
|
||||
#define SCTL_DMA { 0, 0 }
|
||||
#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ }
|
||||
#define WATCHDOG_DMA { 0, 0 }
|
||||
#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ }
|
||||
#define GPIO0_DMA { 0, 0 }
|
||||
#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ }
|
||||
#define GPIO1_DMA { 0, 0 }
|
||||
#define RTC_IRQ { IRQ_RTCINT, NO_IRQ }
|
||||
#define RTC_DMA { 0, 0 }
|
||||
|
||||
/*
|
||||
* These devices are connected via the DMA APB bridge
|
||||
*/
|
||||
#define SCI_IRQ { IRQ_SCIINT, NO_IRQ }
|
||||
#define SCI_DMA { 7, 6 }
|
||||
#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ }
|
||||
#define UART0_DMA { 15, 14 }
|
||||
#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ }
|
||||
#define UART1_DMA { 13, 12 }
|
||||
#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ }
|
||||
#define UART2_DMA { 11, 10 }
|
||||
#define UART3_IRQ { IRQ_UART3, NO_IRQ }
|
||||
#define UART3_DMA { 0x86, 0x87 }
|
||||
#define SSP_IRQ { IRQ_SSPINT, NO_IRQ }
|
||||
#define SSP_DMA { 9, 8 }
|
||||
|
||||
|
||||
extern struct platform_device realview_flash_device;
|
||||
extern struct platform_device realview_smc91x_device;
|
||||
extern struct mmc_platform_data realview_mmc0_plat_data;
|
||||
extern struct mmc_platform_data realview_mmc1_plat_data;
|
||||
extern struct clk realview_clcd_clk;
|
||||
extern struct clcd_board clcd_plat_data;
|
||||
|
||||
extern void realview_leds_event(led_event_t ledevt);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-realview/realview_eb.c
|
||||
*
|
||||
* Copyright (C) 2004 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/leds.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/hardware/amba.h>
|
||||
#include <asm/hardware/icst307.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/mmc.h>
|
||||
|
||||
#include <asm/arch/irqs.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "clock.h"
|
||||
|
||||
static struct map_desc realview_eb_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = IO_ADDRESS(REALVIEW_SYS_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_SYS_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_GIC_CPU_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_GIC_CPU_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_GIC_DIST_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_SCTL_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_TIMER0_1_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_TIMER0_1_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = IO_ADDRESS(REALVIEW_TIMER2_3_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_TIMER2_3_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
#ifdef CONFIG_DEBUG_LL
|
||||
{
|
||||
.virtual = IO_ADDRESS(REALVIEW_UART0_BASE),
|
||||
.pfn = __phys_to_pfn(REALVIEW_UART0_BASE),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
static void __init realview_eb_map_io(void)
|
||||
{
|
||||
iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc));
|
||||
}
|
||||
|
||||
/* FPGA Primecells */
|
||||
AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
|
||||
AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data);
|
||||
AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL);
|
||||
AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL);
|
||||
AMBA_DEVICE(uart3, "fpga:09", UART3, NULL);
|
||||
|
||||
/* DevChip Primecells */
|
||||
AMBA_DEVICE(smc, "dev:00", SMC, NULL);
|
||||
AMBA_DEVICE(clcd, "dev:20", CLCD, &clcd_plat_data);
|
||||
AMBA_DEVICE(dmac, "dev:30", DMAC, NULL);
|
||||
AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL);
|
||||
AMBA_DEVICE(wdog, "dev:e1", WATCHDOG, NULL);
|
||||
AMBA_DEVICE(gpio0, "dev:e4", GPIO0, NULL);
|
||||
AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL);
|
||||
AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL);
|
||||
AMBA_DEVICE(rtc, "dev:e8", RTC, NULL);
|
||||
AMBA_DEVICE(sci0, "dev:f0", SCI, NULL);
|
||||
AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);
|
||||
AMBA_DEVICE(uart1, "dev:f2", UART1, NULL);
|
||||
AMBA_DEVICE(uart2, "dev:f3", UART2, NULL);
|
||||
AMBA_DEVICE(ssp0, "dev:f4", SSP, NULL);
|
||||
|
||||
static struct amba_device *amba_devs[] __initdata = {
|
||||
&dmac_device,
|
||||
&uart0_device,
|
||||
&uart1_device,
|
||||
&uart2_device,
|
||||
&uart3_device,
|
||||
&smc_device,
|
||||
&clcd_device,
|
||||
&sctl_device,
|
||||
&wdog_device,
|
||||
&gpio0_device,
|
||||
&gpio1_device,
|
||||
&gpio2_device,
|
||||
&rtc_device,
|
||||
&sci0_device,
|
||||
&ssp0_device,
|
||||
&aaci_device,
|
||||
&mmc0_device,
|
||||
&kmi0_device,
|
||||
&kmi1_device,
|
||||
};
|
||||
|
||||
static void __init gic_init_irq(void)
|
||||
{
|
||||
gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE));
|
||||
gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
|
||||
}
|
||||
|
||||
static void __init realview_eb_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
clk_register(&realview_clcd_clk);
|
||||
|
||||
platform_device_register(&realview_flash_device);
|
||||
platform_device_register(&realview_smc91x_device);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
struct amba_device *d = amba_devs[i];
|
||||
amba_device_register(d, &iomem_resource);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LEDS
|
||||
leds_event = realview_leds_event;
|
||||
#endif
|
||||
}
|
||||
|
||||
MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
|
||||
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
|
||||
.phys_ram = 0x00000000,
|
||||
.phys_io = REALVIEW_UART0_BASE,
|
||||
.io_pg_offst = (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc,
|
||||
.boot_params = 0x00000100,
|
||||
.map_io = realview_eb_map_io,
|
||||
.init_irq = gic_init_irq,
|
||||
.timer = &realview_timer,
|
||||
.init_machine = realview_eb_init,
|
||||
MACHINE_END
|
|
@ -17,6 +17,7 @@
|
|||
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
|
||||
* 14-Mar-2005 BJD Fixed __iomem warnings
|
||||
* 20-Sep-2005 BJD Added static to non-exported items
|
||||
* 31-Oct-2005 BJD Added LCD setup for framebuffer
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -43,6 +44,9 @@
|
|||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
|
||||
#include <asm/arch/fb.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "devs.h"
|
||||
|
@ -97,6 +101,66 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
|
|||
}
|
||||
};
|
||||
|
||||
/* framebuffer lcd controller information */
|
||||
|
||||
static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
|
||||
.regs = {
|
||||
.lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \
|
||||
S3C2410_LCDCON1_TFT | \
|
||||
S3C2410_LCDCON1_CLKVAL(0x0C),
|
||||
|
||||
.lcdcon2 = S3C2410_LCDCON2_VBPD(5) | \
|
||||
S3C2410_LCDCON2_LINEVAL(319) | \
|
||||
S3C2410_LCDCON2_VFPD(6) | \
|
||||
S3C2410_LCDCON2_VSPW(2),
|
||||
|
||||
.lcdcon3 = S3C2410_LCDCON3_HBPD(35) | \
|
||||
S3C2410_LCDCON3_HOZVAL(239) | \
|
||||
S3C2410_LCDCON3_HFPD(35),
|
||||
|
||||
.lcdcon4 = S3C2410_LCDCON4_MVAL(0) | \
|
||||
S3C2410_LCDCON4_HSPW(7),
|
||||
|
||||
.lcdcon5 = S3C2410_LCDCON5_INVVLINE |
|
||||
S3C2410_LCDCON5_FRM565 |
|
||||
S3C2410_LCDCON5_HWSWP,
|
||||
},
|
||||
|
||||
.lpcsel = 0xf82,
|
||||
|
||||
.gpccon = 0xaa955699,
|
||||
.gpccon_mask = 0xffc003cc,
|
||||
.gpcup = 0x0000ffff,
|
||||
.gpcup_mask = 0xffffffff,
|
||||
|
||||
.gpdcon = 0xaa95aaa1,
|
||||
.gpdcon_mask = 0xffc0fff0,
|
||||
.gpdup = 0x0000faff,
|
||||
.gpdup_mask = 0xffffffff,
|
||||
|
||||
.fixed_syncs = 1,
|
||||
.width = 240,
|
||||
.height = 320,
|
||||
|
||||
.xres = {
|
||||
.min = 240,
|
||||
.max = 240,
|
||||
.defval = 240,
|
||||
},
|
||||
|
||||
.yres = {
|
||||
.max = 320,
|
||||
.min = 320,
|
||||
.defval = 320,
|
||||
},
|
||||
|
||||
.bpp = {
|
||||
.min = 16,
|
||||
.max = 16,
|
||||
.defval = 16,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *rx3715_devices[] __initdata = {
|
||||
&s3c_device_usb,
|
||||
&s3c_device_lcd,
|
||||
|
@ -123,14 +187,12 @@ static void __init rx3715_init_irq(void)
|
|||
s3c24xx_init_irq();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static void __init rx3715_init_machine(void)
|
||||
{
|
||||
s3c2410_pm_init();
|
||||
s3c24xx_fb_set_platdata(&rx3715_lcdcfg);
|
||||
}
|
||||
#else
|
||||
#define rx3715_init_machine NULL
|
||||
#endif
|
||||
|
||||
|
||||
MACHINE_START(RX3715, "IPAQ-RX3715")
|
||||
/* Maintainer: Ben Dooks <ben@fluff.org> */
|
||||
|
|
|
@ -120,8 +120,8 @@ config CPU_ARM925T
|
|||
|
||||
# ARM926T
|
||||
config CPU_ARM926T
|
||||
bool "Support ARM926T processor" if ARCH_INTEGRATOR
|
||||
depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX
|
||||
bool "Support ARM926T processor"
|
||||
depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB
|
||||
default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX
|
||||
select CPU_32v5
|
||||
select CPU_ABRT_EV5TJ
|
||||
|
@ -242,7 +242,7 @@ config CPU_XSCALE
|
|||
# ARMv6
|
||||
config CPU_V6
|
||||
bool "Support ARM V6 processor"
|
||||
depends on ARCH_INTEGRATOR
|
||||
depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB
|
||||
select CPU_32v6
|
||||
select CPU_ABRT_EV6
|
||||
select CPU_CACHE_V6
|
||||
|
|
|
@ -486,10 +486,17 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
|
|||
|
||||
/*
|
||||
* Ask the machine support to map in the statically mapped devices.
|
||||
* After this point, we can start to touch devices again.
|
||||
*/
|
||||
if (mdesc->map_io)
|
||||
mdesc->map_io();
|
||||
|
||||
/*
|
||||
* Finally flush the tlb again - this ensures that we're in a
|
||||
* consistent state wrt the writebuffer if the writebuffer needs
|
||||
* draining. After this point, we can start to touch devices
|
||||
* again.
|
||||
*/
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -803,7 +803,6 @@ no_apic:
|
|||
|
||||
void __init init_apic_mappings(void)
|
||||
{
|
||||
unsigned int orig_apicid;
|
||||
unsigned long apic_phys;
|
||||
|
||||
/*
|
||||
|
@ -825,11 +824,8 @@ void __init init_apic_mappings(void)
|
|||
* Fetch the APIC ID of the BSP in case we have a
|
||||
* default configuration (or the MP table is broken).
|
||||
*/
|
||||
orig_apicid = boot_cpu_physical_apicid;
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
|
||||
if ((orig_apicid != -1U) && (orig_apicid != boot_cpu_physical_apicid))
|
||||
printk(KERN_WARNING "Boot APIC ID in local APIC unexpected (%d vs %d)",
|
||||
orig_apicid, boot_cpu_physical_apicid);
|
||||
if (boot_cpu_physical_apicid == -1U)
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
{
|
||||
|
@ -1259,81 +1255,40 @@ fastcall void smp_error_interrupt(struct pt_regs *regs)
|
|||
}
|
||||
|
||||
/*
|
||||
* This initializes the IO-APIC and APIC hardware.
|
||||
* This initializes the IO-APIC and APIC hardware if this is
|
||||
* a UP kernel.
|
||||
*/
|
||||
int __init APIC_init(void)
|
||||
int __init APIC_init_uniprocessor (void)
|
||||
{
|
||||
if (enable_local_apic < 0) {
|
||||
printk(KERN_INFO "APIC disabled\n");
|
||||
return -1;
|
||||
}
|
||||
if (enable_local_apic < 0)
|
||||
clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
|
||||
|
||||
/* See if we have a SMP configuration or have forced enabled
|
||||
* the local apic.
|
||||
*/
|
||||
if (!smp_found_config && !acpi_lapic && !cpu_has_apic) {
|
||||
enable_local_apic = -1;
|
||||
if (!smp_found_config && !cpu_has_apic)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Complain if the BIOS pretends there is an apic.
|
||||
* Then get out because we don't have an a local apic.
|
||||
* Complain if the BIOS pretends there is one.
|
||||
*/
|
||||
if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
|
||||
printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
|
||||
boot_cpu_physical_apicid);
|
||||
printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
|
||||
enable_local_apic = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
verify_local_APIC();
|
||||
|
||||
/*
|
||||
* Should not be necessary because the MP table should list the boot
|
||||
* CPU too, but we do it for the sake of robustness anyway.
|
||||
* Makes no sense to do this check in clustered apic mode, so skip it
|
||||
*/
|
||||
if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
|
||||
printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
|
||||
boot_cpu_physical_apicid);
|
||||
physid_set(boot_cpu_physical_apicid, phys_cpu_present_map);
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch from PIC to APIC mode.
|
||||
*/
|
||||
connect_bsp_APIC();
|
||||
|
||||
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
|
||||
|
||||
setup_local_APIC();
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
/*
|
||||
* Now start the IO-APICs
|
||||
*/
|
||||
if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
|
||||
setup_IO_APIC();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init APIC_late_time_init(void)
|
||||
{
|
||||
/* Improve our loops per jiffy estimate */
|
||||
loops_per_jiffy = ((1000 + HZ - 1)/HZ)*cpu_khz;
|
||||
boot_cpu_data.loops_per_jiffy = loops_per_jiffy;
|
||||
cpu_data[0].loops_per_jiffy = loops_per_jiffy;
|
||||
|
||||
/* setup_apic_nmi_watchdog doesn't work properly before cpu_khz is
|
||||
* initialized. So redo it here to ensure the boot cpu is setup
|
||||
* properly.
|
||||
*/
|
||||
if (nmi_watchdog == NMI_LOCAL_APIC)
|
||||
setup_apic_nmi_watchdog();
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
|
||||
IO_APIC_late_time_init();
|
||||
if (smp_found_config)
|
||||
if (!skip_ioapic_setup && nr_ioapics)
|
||||
setup_IO_APIC();
|
||||
#endif
|
||||
setup_boot_APIC_clock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -435,8 +435,4 @@ void __init init_IRQ(void)
|
|||
setup_irq(FPU_IRQ, &fpu_irq);
|
||||
|
||||
irq_ctx_init(smp_processor_id());
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
APIC_init();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2387,15 +2387,11 @@ void __init setup_IO_APIC(void)
|
|||
sync_Arb_IDs();
|
||||
setup_IO_APIC_irqs();
|
||||
init_IO_APIC_traps();
|
||||
check_timer();
|
||||
if (!acpi_ioapic)
|
||||
print_IO_APIC();
|
||||
}
|
||||
|
||||
void __init IO_APIC_late_time_init(void)
|
||||
{
|
||||
check_timer();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after all the initialization is done. If we didnt find any
|
||||
* APIC bugs then we can allow the modify fast path
|
||||
|
|
|
@ -1078,16 +1078,6 @@ void *xquad_portio;
|
|||
EXPORT_SYMBOL(xquad_portio);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fall back to non SMP mode after errors.
|
||||
*
|
||||
*/
|
||||
static __init void disable_smp(void)
|
||||
{
|
||||
cpu_set(0, cpu_sibling_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
}
|
||||
|
||||
static void __init smp_boot_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int apicid, cpu, bit, kicked;
|
||||
|
@ -1100,6 +1090,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
|||
printk("CPU%d: ", 0);
|
||||
print_cpu_info(&cpu_data[0]);
|
||||
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
|
||||
boot_cpu_logical_apicid = logical_smp_processor_id();
|
||||
x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
|
||||
|
||||
|
@ -1111,27 +1102,68 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
|||
cpus_clear(cpu_core_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
|
||||
map_cpu_to_logical_apicid();
|
||||
|
||||
/*
|
||||
* If we couldn't find an SMP configuration at boot time,
|
||||
* get out of here now!
|
||||
*/
|
||||
if (!smp_found_config && !acpi_lapic) {
|
||||
printk(KERN_NOTICE "SMP motherboard not detected.\n");
|
||||
disable_smp();
|
||||
smpboot_clear_io_apic_irqs();
|
||||
phys_cpu_present_map = physid_mask_of_physid(0);
|
||||
if (APIC_init_uniprocessor())
|
||||
printk(KERN_NOTICE "Local APIC not detected."
|
||||
" Using dummy APIC emulation.\n");
|
||||
map_cpu_to_logical_apicid();
|
||||
cpu_set(0, cpu_sibling_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If SMP should be disabled, then really disable it!
|
||||
* Should not be necessary because the MP table should list the boot
|
||||
* CPU too, but we do it for the sake of robustness anyway.
|
||||
* Makes no sense to do this check in clustered apic mode, so skip it
|
||||
*/
|
||||
if (!max_cpus || (enable_local_apic < 0)) {
|
||||
printk(KERN_INFO "SMP mode deactivated.\n");
|
||||
disable_smp();
|
||||
if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
|
||||
printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
|
||||
boot_cpu_physical_apicid);
|
||||
physid_set(hard_smp_processor_id(), phys_cpu_present_map);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we couldn't find a local APIC, then get out of here now!
|
||||
*/
|
||||
if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
|
||||
printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
|
||||
boot_cpu_physical_apicid);
|
||||
printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
|
||||
smpboot_clear_io_apic_irqs();
|
||||
phys_cpu_present_map = physid_mask_of_physid(0);
|
||||
cpu_set(0, cpu_sibling_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
verify_local_APIC();
|
||||
|
||||
/*
|
||||
* If SMP should be disabled, then really disable it!
|
||||
*/
|
||||
if (!max_cpus) {
|
||||
smp_found_config = 0;
|
||||
printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
|
||||
smpboot_clear_io_apic_irqs();
|
||||
phys_cpu_present_map = physid_mask_of_physid(0);
|
||||
cpu_set(0, cpu_sibling_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
connect_bsp_APIC();
|
||||
setup_local_APIC();
|
||||
map_cpu_to_logical_apicid();
|
||||
|
||||
|
||||
setup_portio_remap();
|
||||
|
||||
/*
|
||||
|
@ -1212,6 +1244,10 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
|
|||
cpu_set(0, cpu_sibling_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
|
||||
smpboot_setup_io_apic();
|
||||
|
||||
setup_boot_APIC_clock();
|
||||
|
||||
/*
|
||||
* Synchronize the TSC with the AP
|
||||
*/
|
||||
|
|
|
@ -440,8 +440,8 @@ static int time_init_device(void)
|
|||
|
||||
device_initcall(time_init_device);
|
||||
|
||||
extern void (*late_time_init)(void);
|
||||
#ifdef CONFIG_HPET_TIMER
|
||||
extern void (*late_time_init)(void);
|
||||
/* Duplicate of time_init() below, with hpet_enable part added */
|
||||
static void __init hpet_time_init(void)
|
||||
{
|
||||
|
@ -458,11 +458,6 @@ static void __init hpet_time_init(void)
|
|||
printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
|
||||
|
||||
time_init_hook();
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
if (enable_local_apic >= 0)
|
||||
APIC_late_time_init();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -487,9 +482,4 @@ void __init time_init(void)
|
|||
printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
|
||||
|
||||
time_init_hook();
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
if (enable_local_apic >= 0)
|
||||
late_time_init = APIC_late_time_init;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
|
|||
*/
|
||||
static u16 toshiba_line_size;
|
||||
|
||||
static struct dmi_system_id __devinit toshiba_ohci1394_dmi_table[] = {
|
||||
static struct dmi_system_id __devinitdata toshiba_ohci1394_dmi_table[] = {
|
||||
{
|
||||
.ident = "Toshiba PS5 based laptop",
|
||||
.matches = {
|
||||
|
|
|
@ -26,6 +26,10 @@ config MMU
|
|||
bool
|
||||
default y
|
||||
|
||||
config SWIOTLB
|
||||
bool
|
||||
default y
|
||||
|
||||
config RWSEM_XCHGADD_ALGORITHM
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -9,7 +9,7 @@ lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
|
|||
bitop.o checksum.o clear_page.o csum_partial_copy.o \
|
||||
clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \
|
||||
flush.o ip_fast_csum.o do_csum.o \
|
||||
memset.o strlen.o swiotlb.o
|
||||
memset.o strlen.o
|
||||
|
||||
lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o
|
||||
lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o
|
||||
|
|
|
@ -99,7 +99,7 @@ CONFIG_M5272C3=y
|
|||
# CONFIG_NETtel is not set
|
||||
# CONFIG_CPU16B is not set
|
||||
# CONFIG_MOD5272 is not set
|
||||
CONFIG_MOTOROLA=y
|
||||
CONFIG_FREESCALE=y
|
||||
# CONFIG_LARGE_ALLOCS is not set
|
||||
CONFIG_4KSTACKS=y
|
||||
CONFIG_RAMAUTO=y
|
||||
|
@ -554,7 +554,6 @@ CONFIG_EXT2_FS=y
|
|||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_MINIX_FS is not set
|
||||
CONFIG_ROMFS_FS=y
|
||||
CONFIG_MAGIC_ROM_PTR=y
|
||||
# CONFIG_INOTIFY is not set
|
||||
# CONFIG_QUOTA is not set
|
||||
# CONFIG_DNOTIFY is not set
|
||||
|
|
|
@ -279,7 +279,7 @@ _GLOBAL(ppc32_rt_sigsuspend)
|
|||
bne syscall_exit
|
||||
/* If sigsuspend() returns zero, we are going into a signal handler. We
|
||||
may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
|
||||
#ifdef CONFIG_AUDIT
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
ld r3,PACACURRENT(r13)
|
||||
ld r4,AUDITCONTEXT(r3)
|
||||
cmpdi 0,r4,0
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
#ifndef __UM_NET_KERN_H
|
||||
#define __UM_NET_KERN_H
|
||||
|
||||
#include "linux/netdevice.h"
|
||||
#include "linux/skbuff.h"
|
||||
#include "linux/socket.h"
|
||||
#include "linux/list.h"
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
struct uml_net {
|
||||
struct list_head list;
|
||||
|
|
|
@ -27,7 +27,6 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/
|
|||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
|
||||
obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o
|
||||
obj-$(CONFIG_SWIOTLB) += swiotlb.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||
obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
|
||||
|
||||
|
@ -41,7 +40,6 @@ CFLAGS_vsyscall.o := $(PROFILING) -g0
|
|||
bootflag-y += ../../i386/kernel/bootflag.o
|
||||
cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o
|
||||
topology-y += ../../i386/mach-default/topology.o
|
||||
swiotlb-$(CONFIG_SWIOTLB) += ../../ia64/lib/swiotlb.o
|
||||
microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o
|
||||
intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
|
||||
quirks-y += ../../i386/kernel/quirks.o
|
||||
|
|
|
@ -5,19 +5,23 @@
|
|||
#undef find_first_bit
|
||||
#undef find_next_bit
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit-number of the first zero bit, not the number of the byte
|
||||
* containing a bit.
|
||||
*/
|
||||
inline long find_first_zero_bit(const unsigned long * addr, unsigned long size)
|
||||
static inline long
|
||||
__find_first_zero_bit(const unsigned long * addr, unsigned long size)
|
||||
{
|
||||
long d0, d1, d2;
|
||||
long res;
|
||||
|
||||
/*
|
||||
* We must test the size in words, not in bits, because
|
||||
* otherwise incoming sizes in the range -63..-1 will not run
|
||||
* any scasq instructions, and then the flags used by the je
|
||||
* instruction will have whatever random value was in place
|
||||
* before. Nobody should call us like that, but
|
||||
* find_next_zero_bit() does when offset and size are at the
|
||||
* same word and it fails to find a zero itself.
|
||||
*/
|
||||
size += 63;
|
||||
size >>= 6;
|
||||
if (!size)
|
||||
return 0;
|
||||
asm volatile(
|
||||
|
@ -30,11 +34,29 @@ inline long find_first_zero_bit(const unsigned long * addr, unsigned long size)
|
|||
" shlq $3,%%rdi\n"
|
||||
" addq %%rdi,%%rdx"
|
||||
:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
|
||||
:"0" (0ULL), "1" ((size + 63) >> 6), "2" (addr), "3" (-1ULL),
|
||||
[addr] "r" (addr) : "memory");
|
||||
:"0" (0ULL), "1" (size), "2" (addr), "3" (-1ULL),
|
||||
[addr] "S" (addr) : "memory");
|
||||
/*
|
||||
* Any register would do for [addr] above, but GCC tends to
|
||||
* prefer rbx over rsi, even though rsi is readily available
|
||||
* and doesn't have to be saved.
|
||||
*/
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit-number of the first zero bit, not the number of the byte
|
||||
* containing a bit.
|
||||
*/
|
||||
long find_first_zero_bit(const unsigned long * addr, unsigned long size)
|
||||
{
|
||||
return __find_first_zero_bit (addr, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* find_next_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
|
@ -43,7 +65,7 @@ inline long find_first_zero_bit(const unsigned long * addr, unsigned long size)
|
|||
*/
|
||||
long find_next_zero_bit (const unsigned long * addr, long size, long offset)
|
||||
{
|
||||
unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
|
||||
const unsigned long * p = addr + (offset >> 6);
|
||||
unsigned long set = 0;
|
||||
unsigned long res, bit = offset&63;
|
||||
|
||||
|
@ -63,8 +85,8 @@ long find_next_zero_bit (const unsigned long * addr, long size, long offset)
|
|||
/*
|
||||
* No zero yet, search remaining full words for a zero
|
||||
*/
|
||||
res = find_first_zero_bit ((const unsigned long *)p,
|
||||
size - 64 * (p - (unsigned long *) addr));
|
||||
res = __find_first_zero_bit (p, size - 64 * (p - addr));
|
||||
|
||||
return (offset + set + res);
|
||||
}
|
||||
|
||||
|
@ -74,6 +96,19 @@ __find_first_bit(const unsigned long * addr, unsigned long size)
|
|||
long d0, d1;
|
||||
long res;
|
||||
|
||||
/*
|
||||
* We must test the size in words, not in bits, because
|
||||
* otherwise incoming sizes in the range -63..-1 will not run
|
||||
* any scasq instructions, and then the flags used by the jz
|
||||
* instruction will have whatever random value was in place
|
||||
* before. Nobody should call us like that, but
|
||||
* find_next_bit() does when offset and size are at the same
|
||||
* word and it fails to find a one itself.
|
||||
*/
|
||||
size += 63;
|
||||
size >>= 6;
|
||||
if (!size)
|
||||
return 0;
|
||||
asm volatile(
|
||||
" repe; scasq\n"
|
||||
" jz 1f\n"
|
||||
|
@ -83,8 +118,7 @@ __find_first_bit(const unsigned long * addr, unsigned long size)
|
|||
" shlq $3,%%rdi\n"
|
||||
" addq %%rdi,%%rax"
|
||||
:"=a" (res), "=&c" (d0), "=&D" (d1)
|
||||
:"0" (0ULL),
|
||||
"1" ((size + 63) >> 6), "2" (addr),
|
||||
:"0" (0ULL), "1" (size), "2" (addr),
|
||||
[addr] "r" (addr) : "memory");
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -468,16 +468,11 @@ aoecmd_ata_rsp(struct sk_buff *skb)
|
|||
unsigned long duration = jiffies - buf->start_time;
|
||||
unsigned long n_sect = buf->bio->bi_size >> 9;
|
||||
struct gendisk *disk = d->gd;
|
||||
const int rw = bio_data_dir(buf->bio);
|
||||
|
||||
if (bio_data_dir(buf->bio) == WRITE) {
|
||||
disk_stat_inc(disk, writes);
|
||||
disk_stat_add(disk, write_ticks, duration);
|
||||
disk_stat_add(disk, write_sectors, n_sect);
|
||||
} else {
|
||||
disk_stat_inc(disk, reads);
|
||||
disk_stat_add(disk, read_ticks, duration);
|
||||
disk_stat_add(disk, read_sectors, n_sect);
|
||||
}
|
||||
disk_stat_inc(disk, ios[rw]);
|
||||
disk_stat_add(disk, ticks[rw], duration);
|
||||
disk_stat_add(disk, sectors[rw], n_sect);
|
||||
disk_stat_add(disk, io_ticks, duration);
|
||||
n = (buf->flags & BUFFL_FAIL) ? -EIO : 0;
|
||||
bio_endio(buf->bio, buf->bio->bi_size, n);
|
||||
|
|
|
@ -369,9 +369,14 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
|
|||
case ELEVATOR_INSERT_SORT:
|
||||
BUG_ON(!blk_fs_request(rq));
|
||||
rq->flags |= REQ_SORTED;
|
||||
q->elevator->ops->elevator_add_req_fn(q, rq);
|
||||
if (q->last_merge == NULL && rq_mergeable(rq))
|
||||
q->last_merge = rq;
|
||||
/*
|
||||
* Some ioscheds (cfq) run q->request_fn directly, so
|
||||
* rq cannot be accessed after calling
|
||||
* elevator_add_req_fn.
|
||||
*/
|
||||
q->elevator->ops->elevator_add_req_fn(q, rq);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -391,13 +391,12 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
|
|||
"%8u %8u %8llu %8u "
|
||||
"%8u %8u %8u"
|
||||
"\n",
|
||||
disk_stat_read(disk, reads), disk_stat_read(disk, read_merges),
|
||||
(unsigned long long)disk_stat_read(disk, read_sectors),
|
||||
jiffies_to_msecs(disk_stat_read(disk, read_ticks)),
|
||||
disk_stat_read(disk, writes),
|
||||
disk_stat_read(disk, write_merges),
|
||||
(unsigned long long)disk_stat_read(disk, write_sectors),
|
||||
jiffies_to_msecs(disk_stat_read(disk, write_ticks)),
|
||||
disk_stat_read(disk, ios[0]), disk_stat_read(disk, merges[0]),
|
||||
(unsigned long long)disk_stat_read(disk, sectors[0]),
|
||||
jiffies_to_msecs(disk_stat_read(disk, ticks[0])),
|
||||
disk_stat_read(disk, ios[1]), disk_stat_read(disk, merges[1]),
|
||||
(unsigned long long)disk_stat_read(disk, sectors[1]),
|
||||
jiffies_to_msecs(disk_stat_read(disk, ticks[1])),
|
||||
disk->in_flight,
|
||||
jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
|
||||
jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
|
||||
|
@ -583,12 +582,12 @@ static int diskstats_show(struct seq_file *s, void *v)
|
|||
preempt_enable();
|
||||
seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n",
|
||||
gp->major, n + gp->first_minor, disk_name(gp, n, buf),
|
||||
disk_stat_read(gp, reads), disk_stat_read(gp, read_merges),
|
||||
(unsigned long long)disk_stat_read(gp, read_sectors),
|
||||
jiffies_to_msecs(disk_stat_read(gp, read_ticks)),
|
||||
disk_stat_read(gp, writes), disk_stat_read(gp, write_merges),
|
||||
(unsigned long long)disk_stat_read(gp, write_sectors),
|
||||
jiffies_to_msecs(disk_stat_read(gp, write_ticks)),
|
||||
disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
|
||||
(unsigned long long)disk_stat_read(gp, sectors[0]),
|
||||
jiffies_to_msecs(disk_stat_read(gp, ticks[0])),
|
||||
disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]),
|
||||
(unsigned long long)disk_stat_read(gp, sectors[1]),
|
||||
jiffies_to_msecs(disk_stat_read(gp, ticks[1])),
|
||||
gp->in_flight,
|
||||
jiffies_to_msecs(disk_stat_read(gp, io_ticks)),
|
||||
jiffies_to_msecs(disk_stat_read(gp, time_in_queue)));
|
||||
|
@ -601,8 +600,8 @@ static int diskstats_show(struct seq_file *s, void *v)
|
|||
seq_printf(s, "%4d %4d %s %u %u %u %u\n",
|
||||
gp->major, n + gp->first_minor + 1,
|
||||
disk_name(gp, n + 1, buf),
|
||||
hd->reads, hd->read_sectors,
|
||||
hd->writes, hd->write_sectors);
|
||||
hd->ios[0], hd->sectors[0],
|
||||
hd->ios[1], hd->sectors[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2387,16 +2387,9 @@ static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
|
|||
if (!blk_fs_request(rq) || !rq->rq_disk)
|
||||
return;
|
||||
|
||||
if (rw == READ) {
|
||||
__disk_stat_add(rq->rq_disk, read_sectors, nr_sectors);
|
||||
if (!new_io)
|
||||
__disk_stat_inc(rq->rq_disk, read_merges);
|
||||
} else if (rw == WRITE) {
|
||||
__disk_stat_add(rq->rq_disk, write_sectors, nr_sectors);
|
||||
if (!new_io)
|
||||
__disk_stat_inc(rq->rq_disk, write_merges);
|
||||
}
|
||||
if (new_io) {
|
||||
if (!new_io) {
|
||||
__disk_stat_inc(rq->rq_disk, merges[rw]);
|
||||
} else {
|
||||
disk_round_stats(rq->rq_disk);
|
||||
rq->rq_disk->in_flight++;
|
||||
}
|
||||
|
@ -2791,17 +2784,11 @@ static inline void blk_partition_remap(struct bio *bio)
|
|||
|
||||
if (bdev != bdev->bd_contains) {
|
||||
struct hd_struct *p = bdev->bd_part;
|
||||
const int rw = bio_data_dir(bio);
|
||||
|
||||
p->sectors[rw] += bio_sectors(bio);
|
||||
p->ios[rw]++;
|
||||
|
||||
switch (bio_data_dir(bio)) {
|
||||
case READ:
|
||||
p->read_sectors += bio_sectors(bio);
|
||||
p->reads++;
|
||||
break;
|
||||
case WRITE:
|
||||
p->write_sectors += bio_sectors(bio);
|
||||
p->writes++;
|
||||
break;
|
||||
}
|
||||
bio->bi_sector += p->start_sect;
|
||||
bio->bi_bdev = bdev->bd_contains;
|
||||
}
|
||||
|
@ -3048,6 +3035,12 @@ static int __end_that_request_first(struct request *req, int uptodate,
|
|||
(unsigned long long)req->sector);
|
||||
}
|
||||
|
||||
if (blk_fs_request(req) && req->rq_disk) {
|
||||
const int rw = rq_data_dir(req);
|
||||
|
||||
__disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
|
||||
}
|
||||
|
||||
total_bytes = bio_nbytes = 0;
|
||||
while ((bio = req->bio) != NULL) {
|
||||
int nbytes;
|
||||
|
@ -3176,16 +3169,10 @@ void end_that_request_last(struct request *req)
|
|||
|
||||
if (disk && blk_fs_request(req)) {
|
||||
unsigned long duration = jiffies - req->start_time;
|
||||
switch (rq_data_dir(req)) {
|
||||
case WRITE:
|
||||
__disk_stat_inc(disk, writes);
|
||||
__disk_stat_add(disk, write_ticks, duration);
|
||||
break;
|
||||
case READ:
|
||||
__disk_stat_inc(disk, reads);
|
||||
__disk_stat_add(disk, read_ticks, duration);
|
||||
break;
|
||||
}
|
||||
const int rw = rq_data_dir(req);
|
||||
|
||||
__disk_stat_inc(disk, ios[rw]);
|
||||
__disk_stat_add(disk, ticks[rw], duration);
|
||||
disk_round_stats(disk);
|
||||
disk->in_flight--;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file ati_pcigart.h
|
||||
* \file ati_pcigart.c
|
||||
* ATI PCI GART support
|
||||
*
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
|
@ -52,85 +52,91 @@
|
|||
# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
|
||||
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
|
||||
|
||||
static unsigned long drm_ati_alloc_pcigart_table( void )
|
||||
static unsigned long drm_ati_alloc_pcigart_table(void)
|
||||
{
|
||||
unsigned long address;
|
||||
struct page *page;
|
||||
int i;
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
|
||||
if ( address == 0UL ) {
|
||||
address = __get_free_pages(GFP_KERNEL, ATI_PCIGART_TABLE_ORDER);
|
||||
if (address == 0UL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
page = virt_to_page( address );
|
||||
page = virt_to_page(address);
|
||||
|
||||
for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||
for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
|
||||
get_page(page);
|
||||
SetPageReserved( page );
|
||||
SetPageReserved(page);
|
||||
}
|
||||
|
||||
DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
|
||||
DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
|
||||
return address;
|
||||
}
|
||||
|
||||
static void drm_ati_free_pcigart_table( unsigned long address )
|
||||
static void drm_ati_free_pcigart_table(unsigned long address)
|
||||
{
|
||||
struct page *page;
|
||||
int i;
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
page = virt_to_page( address );
|
||||
page = virt_to_page(address);
|
||||
|
||||
for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
|
||||
for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
|
||||
__put_page(page);
|
||||
ClearPageReserved( page );
|
||||
ClearPageReserved(page);
|
||||
}
|
||||
|
||||
free_pages( address, ATI_PCIGART_TABLE_ORDER );
|
||||
free_pages(address, ATI_PCIGART_TABLE_ORDER);
|
||||
}
|
||||
|
||||
int drm_ati_pcigart_cleanup( drm_device_t *dev,
|
||||
unsigned long addr,
|
||||
dma_addr_t bus_addr)
|
||||
int drm_ati_pcigart_cleanup(drm_device_t * dev,
|
||||
drm_ati_pcigart_info * gart_info)
|
||||
{
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long pages;
|
||||
int i;
|
||||
|
||||
/* we need to support large memory configurations */
|
||||
if ( !entry ) {
|
||||
DRM_ERROR( "no scatter/gather memory!\n" );
|
||||
if (!entry) {
|
||||
DRM_ERROR("no scatter/gather memory!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( bus_addr ) {
|
||||
pci_unmap_single(dev->pdev, bus_addr,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (gart_info->bus_addr) {
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
pci_unmap_single(dev->pdev, gart_info->bus_addr,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
if ( !entry->busaddr[i] ) break;
|
||||
for (i = 0; i < pages; i++) {
|
||||
if (!entry->busaddr[i])
|
||||
break;
|
||||
pci_unmap_single(dev->pdev, entry->busaddr[i],
|
||||
PAGE_SIZE, PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
|
||||
gart_info->bus_addr = 0;
|
||||
}
|
||||
|
||||
if ( addr ) {
|
||||
drm_ati_free_pcigart_table( addr );
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
|
||||
&& gart_info->addr) {
|
||||
drm_ati_free_pcigart_table(gart_info->addr);
|
||||
gart_info->addr = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
|
||||
|
||||
int drm_ati_pcigart_init( drm_device_t *dev,
|
||||
unsigned long *addr,
|
||||
dma_addr_t *bus_addr)
|
||||
int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
|
||||
{
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long address = 0;
|
||||
|
@ -138,48 +144,57 @@ int drm_ati_pcigart_init( drm_device_t *dev,
|
|||
u32 *pci_gart, page_base, bus_address = 0;
|
||||
int i, j, ret = 0;
|
||||
|
||||
if ( !entry ) {
|
||||
DRM_ERROR( "no scatter/gather memory!\n" );
|
||||
if (!entry) {
|
||||
DRM_ERROR("no scatter/gather memory!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
address = drm_ati_alloc_pcigart_table();
|
||||
if ( !address ) {
|
||||
DRM_ERROR( "cannot allocate PCI GART page!\n" );
|
||||
goto done;
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
|
||||
|
||||
address = drm_ati_alloc_pcigart_table();
|
||||
if (!address) {
|
||||
DRM_ERROR("cannot allocate PCI GART page!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!dev->pdev) {
|
||||
DRM_ERROR("PCI device unknown!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
bus_address = pci_map_single(dev->pdev, (void *)address,
|
||||
ATI_PCIGART_TABLE_PAGES *
|
||||
PAGE_SIZE, PCI_DMA_TODEVICE);
|
||||
if (bus_address == 0) {
|
||||
DRM_ERROR("unable to map PCIGART pages!\n");
|
||||
drm_ati_free_pcigart_table(address);
|
||||
address = 0;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
address = gart_info->addr;
|
||||
bus_address = gart_info->bus_addr;
|
||||
DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
|
||||
bus_address, address);
|
||||
}
|
||||
|
||||
if ( !dev->pdev ) {
|
||||
DRM_ERROR( "PCI device unknown!\n" );
|
||||
goto done;
|
||||
}
|
||||
pci_gart = (u32 *) address;
|
||||
|
||||
bus_address = pci_map_single(dev->pdev, (void *)address,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (bus_address == 0) {
|
||||
DRM_ERROR( "unable to map PCIGART pages!\n" );
|
||||
drm_ati_free_pcigart_table( address );
|
||||
address = 0;
|
||||
goto done;
|
||||
}
|
||||
pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
|
||||
pci_gart = (u32 *)address;
|
||||
memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32));
|
||||
|
||||
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
|
||||
memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
|
||||
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
for (i = 0; i < pages; i++) {
|
||||
/* we need to support large memory configurations */
|
||||
entry->busaddr[i] = pci_map_single(dev->pdev,
|
||||
page_address( entry->pagelist[i] ),
|
||||
PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
page_address(entry->
|
||||
pagelist[i]),
|
||||
PAGE_SIZE, PCI_DMA_TODEVICE);
|
||||
if (entry->busaddr[i] == 0) {
|
||||
DRM_ERROR( "unable to map PCIGART pages!\n" );
|
||||
drm_ati_pcigart_cleanup( dev, address, bus_address );
|
||||
DRM_ERROR("unable to map PCIGART pages!\n");
|
||||
drm_ati_pcigart_cleanup(dev, gart_info);
|
||||
address = 0;
|
||||
bus_address = 0;
|
||||
goto done;
|
||||
|
@ -187,7 +202,11 @@ int drm_ati_pcigart_init( drm_device_t *dev,
|
|||
page_base = (u32) entry->busaddr[i];
|
||||
|
||||
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
|
||||
*pci_gart++ = cpu_to_le32( page_base );
|
||||
if (gart_info->is_pcie)
|
||||
*pci_gart = (cpu_to_le32(page_base) >> 8) | 0xc;
|
||||
else
|
||||
*pci_gart = cpu_to_le32(page_base);
|
||||
*pci_gart++;
|
||||
page_base += ATI_PCIGART_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
@ -200,9 +219,10 @@ int drm_ati_pcigart_init( drm_device_t *dev,
|
|||
mb();
|
||||
#endif
|
||||
|
||||
done:
|
||||
*addr = address;
|
||||
*bus_addr = bus_address;
|
||||
done:
|
||||
gart_info->addr = address;
|
||||
gart_info->bus_addr = bus_address;
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_ati_pcigart_init);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* \file drm.h
|
||||
* \file drm.h
|
||||
* Header for the Direct Rendering Manager
|
||||
*
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
* \par Acknowledgments:
|
||||
|
@ -33,7 +33,6 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DRM_H_
|
||||
#define _DRM_H_
|
||||
|
||||
|
@ -56,7 +55,7 @@
|
|||
#define ioctl(a,b,c) xf86ioctl(a,b,c)
|
||||
#else
|
||||
#include <sys/ioccom.h>
|
||||
#endif /* __FreeBSD__ && xf86ioctl */
|
||||
#endif /* __FreeBSD__ && xf86ioctl */
|
||||
#define DRM_IOCTL_NR(n) ((n) & 0xff)
|
||||
#define DRM_IOC_VOID IOC_VOID
|
||||
#define DRM_IOC_READ IOC_OUT
|
||||
|
@ -97,16 +96,14 @@
|
|||
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
|
||||
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
|
||||
|
||||
|
||||
typedef unsigned int drm_handle_t;
|
||||
typedef unsigned int drm_context_t;
|
||||
typedef unsigned int drm_drawable_t;
|
||||
typedef unsigned int drm_magic_t;
|
||||
|
||||
typedef unsigned int drm_handle_t;
|
||||
typedef unsigned int drm_context_t;
|
||||
typedef unsigned int drm_drawable_t;
|
||||
typedef unsigned int drm_magic_t;
|
||||
|
||||
/**
|
||||
* Cliprect.
|
||||
*
|
||||
*
|
||||
* \warning: If you change this structure, make sure you change
|
||||
* XF86DRIClipRectRec in the server as well
|
||||
*
|
||||
|
@ -114,22 +111,21 @@ typedef unsigned int drm_magic_t;
|
|||
* backwards-compatibility reasons.
|
||||
*/
|
||||
typedef struct drm_clip_rect {
|
||||
unsigned short x1;
|
||||
unsigned short y1;
|
||||
unsigned short x2;
|
||||
unsigned short y2;
|
||||
unsigned short x1;
|
||||
unsigned short y1;
|
||||
unsigned short x2;
|
||||
unsigned short y2;
|
||||
} drm_clip_rect_t;
|
||||
|
||||
|
||||
/**
|
||||
* Texture region,
|
||||
*/
|
||||
typedef struct drm_tex_region {
|
||||
unsigned char next;
|
||||
unsigned char prev;
|
||||
unsigned char in_use;
|
||||
unsigned char padding;
|
||||
unsigned int age;
|
||||
unsigned char next;
|
||||
unsigned char prev;
|
||||
unsigned char in_use;
|
||||
unsigned char padding;
|
||||
unsigned int age;
|
||||
} drm_tex_region_t;
|
||||
|
||||
/**
|
||||
|
@ -141,28 +137,26 @@ typedef struct drm_tex_region {
|
|||
*/
|
||||
typedef struct drm_hw_lock {
|
||||
__volatile__ unsigned int lock; /**< lock variable */
|
||||
char padding[60]; /**< Pad to cache line */
|
||||
char padding[60]; /**< Pad to cache line */
|
||||
} drm_hw_lock_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_VERSION ioctl argument type.
|
||||
*
|
||||
*
|
||||
* \sa drmGetVersion().
|
||||
*/
|
||||
typedef struct drm_version {
|
||||
int version_major; /**< Major version */
|
||||
int version_minor; /**< Minor version */
|
||||
int version_patchlevel;/**< Patch level */
|
||||
int version_major; /**< Major version */
|
||||
int version_minor; /**< Minor version */
|
||||
int version_patchlevel; /**< Patch level */
|
||||
size_t name_len; /**< Length of name buffer */
|
||||
char __user *name; /**< Name of driver */
|
||||
char __user *name; /**< Name of driver */
|
||||
size_t date_len; /**< Length of date buffer */
|
||||
char __user *date; /**< User-space buffer to hold date */
|
||||
char __user *date; /**< User-space buffer to hold date */
|
||||
size_t desc_len; /**< Length of desc buffer */
|
||||
char __user *desc; /**< User-space buffer to hold desc */
|
||||
char __user *desc; /**< User-space buffer to hold desc */
|
||||
} drm_version_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_UNIQUE ioctl argument type.
|
||||
*
|
||||
|
@ -170,21 +164,18 @@ typedef struct drm_version {
|
|||
*/
|
||||
typedef struct drm_unique {
|
||||
size_t unique_len; /**< Length of unique */
|
||||
char __user *unique; /**< Unique name for driver instantiation */
|
||||
char __user *unique; /**< Unique name for driver instantiation */
|
||||
} drm_unique_t;
|
||||
|
||||
|
||||
typedef struct drm_list {
|
||||
int count; /**< Length of user-space structures */
|
||||
drm_version_t __user *version;
|
||||
int count; /**< Length of user-space structures */
|
||||
drm_version_t __user *version;
|
||||
} drm_list_t;
|
||||
|
||||
|
||||
typedef struct drm_block {
|
||||
int unused;
|
||||
int unused;
|
||||
} drm_block_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_CONTROL ioctl argument type.
|
||||
*
|
||||
|
@ -196,44 +187,40 @@ typedef struct drm_control {
|
|||
DRM_RM_COMMAND,
|
||||
DRM_INST_HANDLER,
|
||||
DRM_UNINST_HANDLER
|
||||
} func;
|
||||
int irq;
|
||||
} func;
|
||||
int irq;
|
||||
} drm_control_t;
|
||||
|
||||
|
||||
/**
|
||||
* Type of memory to map.
|
||||
*/
|
||||
typedef enum drm_map_type {
|
||||
_DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /**< no caching, no core dump */
|
||||
_DRM_SHM = 2, /**< shared, cached */
|
||||
_DRM_AGP = 3, /**< AGP/GART */
|
||||
_DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /**< no caching, no core dump */
|
||||
_DRM_SHM = 2, /**< shared, cached */
|
||||
_DRM_AGP = 3, /**< AGP/GART */
|
||||
_DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
|
||||
_DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
|
||||
_DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
|
||||
} drm_map_type_t;
|
||||
|
||||
|
||||
/**
|
||||
* Memory mapping flags.
|
||||
*/
|
||||
typedef enum drm_map_flags {
|
||||
_DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
|
||||
_DRM_READ_ONLY = 0x02,
|
||||
_DRM_LOCKED = 0x04, /**< shared, cached, locked */
|
||||
_DRM_KERNEL = 0x08, /**< kernel requires access */
|
||||
_DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
|
||||
_DRM_READ_ONLY = 0x02,
|
||||
_DRM_LOCKED = 0x04, /**< shared, cached, locked */
|
||||
_DRM_KERNEL = 0x08, /**< kernel requires access */
|
||||
_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
|
||||
_DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
|
||||
_DRM_REMOVABLE = 0x40 /**< Removable mapping */
|
||||
_DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
|
||||
_DRM_REMOVABLE = 0x40 /**< Removable mapping */
|
||||
} drm_map_flags_t;
|
||||
|
||||
|
||||
typedef struct drm_ctx_priv_map {
|
||||
unsigned int ctx_id; /**< Context requesting private mapping */
|
||||
void *handle; /**< Handle of map */
|
||||
unsigned int ctx_id; /**< Context requesting private mapping */
|
||||
void *handle; /**< Handle of map */
|
||||
} drm_ctx_priv_map_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
|
||||
* argument type.
|
||||
|
@ -241,30 +228,28 @@ typedef struct drm_ctx_priv_map {
|
|||
* \sa drmAddMap().
|
||||
*/
|
||||
typedef struct drm_map {
|
||||
unsigned long offset; /**< Requested physical address (0 for SAREA)*/
|
||||
unsigned long size; /**< Requested physical size (bytes) */
|
||||
drm_map_type_t type; /**< Type of memory to map */
|
||||
unsigned long offset; /**< Requested physical address (0 for SAREA)*/
|
||||
unsigned long size; /**< Requested physical size (bytes) */
|
||||
drm_map_type_t type; /**< Type of memory to map */
|
||||
drm_map_flags_t flags; /**< Flags */
|
||||
void *handle; /**< User-space: "Handle" to pass to mmap() */
|
||||
void *handle; /**< User-space: "Handle" to pass to mmap() */
|
||||
/**< Kernel-space: kernel-virtual address */
|
||||
int mtrr; /**< MTRR slot used */
|
||||
/* Private data */
|
||||
int mtrr; /**< MTRR slot used */
|
||||
/* Private data */
|
||||
} drm_map_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_CLIENT ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_client {
|
||||
int idx; /**< Which client desired? */
|
||||
int auth; /**< Is client authenticated? */
|
||||
unsigned long pid; /**< Process ID */
|
||||
unsigned long uid; /**< User ID */
|
||||
unsigned long magic; /**< Magic */
|
||||
unsigned long iocs; /**< Ioctl count */
|
||||
int idx; /**< Which client desired? */
|
||||
int auth; /**< Is client authenticated? */
|
||||
unsigned long pid; /**< Process ID */
|
||||
unsigned long uid; /**< User ID */
|
||||
unsigned long magic; /**< Magic */
|
||||
unsigned long iocs; /**< Ioctl count */
|
||||
} drm_client_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
_DRM_STAT_LOCK,
|
||||
_DRM_STAT_OPENS,
|
||||
|
@ -282,63 +267,58 @@ typedef enum {
|
|||
_DRM_STAT_DMA, /**< DMA */
|
||||
_DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
|
||||
_DRM_STAT_MISSED /**< Missed DMA opportunity */
|
||||
|
||||
/* Add to the *END* of the list */
|
||||
/* Add to the *END* of the list */
|
||||
} drm_stat_type_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_STATS ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_stats {
|
||||
unsigned long count;
|
||||
struct {
|
||||
unsigned long value;
|
||||
unsigned long value;
|
||||
drm_stat_type_t type;
|
||||
} data[15];
|
||||
} drm_stats_t;
|
||||
|
||||
|
||||
/**
|
||||
* Hardware locking flags.
|
||||
*/
|
||||
typedef enum drm_lock_flags {
|
||||
_DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
|
||||
_DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
|
||||
_DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
|
||||
_DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
|
||||
/* These *HALT* flags aren't supported yet
|
||||
-- they will be used to support the
|
||||
full-screen DGA-like mode. */
|
||||
_DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
|
||||
_DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
|
||||
_DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
|
||||
_DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
|
||||
/* These *HALT* flags aren't supported yet
|
||||
-- they will be used to support the
|
||||
full-screen DGA-like mode. */
|
||||
_DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
|
||||
_DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
|
||||
} drm_lock_flags_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
|
||||
*
|
||||
*
|
||||
* \sa drmGetLock() and drmUnlock().
|
||||
*/
|
||||
typedef struct drm_lock {
|
||||
int context;
|
||||
int context;
|
||||
drm_lock_flags_t flags;
|
||||
} drm_lock_t;
|
||||
|
||||
|
||||
/**
|
||||
* DMA flags
|
||||
*
|
||||
* \warning
|
||||
* \warning
|
||||
* These values \e must match xf86drm.h.
|
||||
*
|
||||
* \sa drm_dma.
|
||||
*/
|
||||
typedef enum drm_dma_flags {
|
||||
/* Flags for DMA buffer dispatch */
|
||||
_DRM_DMA_BLOCK = 0x01, /**<
|
||||
typedef enum drm_dma_flags {
|
||||
/* Flags for DMA buffer dispatch */
|
||||
_DRM_DMA_BLOCK = 0x01, /**<
|
||||
* Block until buffer dispatched.
|
||||
*
|
||||
*
|
||||
* \note The buffer may not yet have
|
||||
* been processed by the hardware --
|
||||
* getting a hardware lock with the
|
||||
|
@ -347,79 +327,73 @@ typedef enum drm_dma_flags {
|
|||
* processed.
|
||||
*/
|
||||
_DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
|
||||
_DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
|
||||
_DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
|
||||
|
||||
/* Flags for DMA buffer request */
|
||||
_DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
|
||||
_DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
|
||||
_DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
|
||||
/* Flags for DMA buffer request */
|
||||
_DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
|
||||
_DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
|
||||
_DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
|
||||
} drm_dma_flags_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
|
||||
*
|
||||
* \sa drmAddBufs().
|
||||
*/
|
||||
typedef struct drm_buf_desc {
|
||||
int count; /**< Number of buffers of this size */
|
||||
int size; /**< Size in bytes */
|
||||
int low_mark; /**< Low water mark */
|
||||
int high_mark; /**< High water mark */
|
||||
int count; /**< Number of buffers of this size */
|
||||
int size; /**< Size in bytes */
|
||||
int low_mark; /**< Low water mark */
|
||||
int high_mark; /**< High water mark */
|
||||
enum {
|
||||
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
|
||||
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
|
||||
_DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
|
||||
_DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */
|
||||
} flags;
|
||||
unsigned long agp_start; /**<
|
||||
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
|
||||
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
|
||||
_DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
|
||||
_DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */
|
||||
} flags;
|
||||
unsigned long agp_start; /**<
|
||||
* Start address of where the AGP buffers are
|
||||
* in the AGP aperture
|
||||
*/
|
||||
} drm_buf_desc_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_INFO_BUFS ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_buf_info {
|
||||
int count; /**< Entries in list */
|
||||
int count; /**< Entries in list */
|
||||
drm_buf_desc_t __user *list;
|
||||
} drm_buf_info_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_FREE_BUFS ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_buf_free {
|
||||
int count;
|
||||
int __user *list;
|
||||
int count;
|
||||
int __user *list;
|
||||
} drm_buf_free_t;
|
||||
|
||||
|
||||
/**
|
||||
* Buffer information
|
||||
*
|
||||
* \sa drm_buf_map.
|
||||
*/
|
||||
typedef struct drm_buf_pub {
|
||||
int idx; /**< Index into the master buffer list */
|
||||
int total; /**< Buffer size */
|
||||
int used; /**< Amount of buffer in use (for DMA) */
|
||||
void __user *address; /**< Address of buffer */
|
||||
int idx; /**< Index into the master buffer list */
|
||||
int total; /**< Buffer size */
|
||||
int used; /**< Amount of buffer in use (for DMA) */
|
||||
void __user *address; /**< Address of buffer */
|
||||
} drm_buf_pub_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_MAP_BUFS ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_buf_map {
|
||||
int count; /**< Length of the buffer list */
|
||||
void __user *virtual; /**< Mmap'd area in user-virtual */
|
||||
int count; /**< Length of the buffer list */
|
||||
void __user *virtual; /**< Mmap'd area in user-virtual */
|
||||
drm_buf_pub_t __user *list; /**< Buffer information */
|
||||
} drm_buf_map_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_DMA ioctl argument type.
|
||||
*
|
||||
|
@ -428,61 +402,55 @@ typedef struct drm_buf_map {
|
|||
* \sa drmDMA().
|
||||
*/
|
||||
typedef struct drm_dma {
|
||||
int context; /**< Context handle */
|
||||
int send_count; /**< Number of buffers to send */
|
||||
int __user *send_indices; /**< List of handles to buffers */
|
||||
int __user *send_sizes; /**< Lengths of data to send */
|
||||
int context; /**< Context handle */
|
||||
int send_count; /**< Number of buffers to send */
|
||||
int __user *send_indices; /**< List of handles to buffers */
|
||||
int __user *send_sizes; /**< Lengths of data to send */
|
||||
drm_dma_flags_t flags; /**< Flags */
|
||||
int request_count; /**< Number of buffers requested */
|
||||
int request_size; /**< Desired size for buffers */
|
||||
int __user *request_indices; /**< Buffer information */
|
||||
int __user *request_sizes;
|
||||
int granted_count; /**< Number of buffers granted */
|
||||
int request_count; /**< Number of buffers requested */
|
||||
int request_size; /**< Desired size for buffers */
|
||||
int __user *request_indices; /**< Buffer information */
|
||||
int __user *request_sizes;
|
||||
int granted_count; /**< Number of buffers granted */
|
||||
} drm_dma_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
_DRM_CONTEXT_PRESERVED = 0x01,
|
||||
_DRM_CONTEXT_2DONLY = 0x02
|
||||
_DRM_CONTEXT_2DONLY = 0x02
|
||||
} drm_ctx_flags_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_CTX ioctl argument type.
|
||||
*
|
||||
* \sa drmCreateContext() and drmDestroyContext().
|
||||
*/
|
||||
typedef struct drm_ctx {
|
||||
drm_context_t handle;
|
||||
drm_context_t handle;
|
||||
drm_ctx_flags_t flags;
|
||||
} drm_ctx_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_RES_CTX ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_ctx_res {
|
||||
int count;
|
||||
drm_ctx_t __user *contexts;
|
||||
int count;
|
||||
drm_ctx_t __user *contexts;
|
||||
} drm_ctx_res_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_draw {
|
||||
drm_drawable_t handle;
|
||||
drm_drawable_t handle;
|
||||
} drm_draw_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_auth {
|
||||
drm_magic_t magic;
|
||||
drm_magic_t magic;
|
||||
} drm_auth_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_IRQ_BUSID ioctl argument type.
|
||||
*
|
||||
|
@ -495,24 +463,20 @@ typedef struct drm_irq_busid {
|
|||
int funcnum; /**< function number */
|
||||
} drm_irq_busid_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
|
||||
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
|
||||
_DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
|
||||
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
|
||||
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
|
||||
_DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
|
||||
} drm_vblank_seq_type_t;
|
||||
|
||||
|
||||
#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
|
||||
|
||||
|
||||
struct drm_wait_vblank_request {
|
||||
drm_vblank_seq_type_t type;
|
||||
unsigned int sequence;
|
||||
unsigned long signal;
|
||||
};
|
||||
|
||||
|
||||
struct drm_wait_vblank_reply {
|
||||
drm_vblank_seq_type_t type;
|
||||
unsigned int sequence;
|
||||
|
@ -520,7 +484,6 @@ struct drm_wait_vblank_reply {
|
|||
long tval_usec;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_WAIT_VBLANK ioctl argument type.
|
||||
*
|
||||
|
@ -531,7 +494,6 @@ typedef union drm_wait_vblank {
|
|||
struct drm_wait_vblank_reply reply;
|
||||
} drm_wait_vblank_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_ENABLE ioctl argument type.
|
||||
*
|
||||
|
@ -541,7 +503,6 @@ typedef struct drm_agp_mode {
|
|||
unsigned long mode; /**< AGP mode */
|
||||
} drm_agp_mode_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
|
||||
*
|
||||
|
@ -550,22 +511,20 @@ typedef struct drm_agp_mode {
|
|||
typedef struct drm_agp_buffer {
|
||||
unsigned long size; /**< In bytes -- will round to page boundary */
|
||||
unsigned long handle; /**< Used for binding / unbinding */
|
||||
unsigned long type; /**< Type of memory to allocate */
|
||||
unsigned long physical; /**< Physical used by i810 */
|
||||
unsigned long type; /**< Type of memory to allocate */
|
||||
unsigned long physical; /**< Physical used by i810 */
|
||||
} drm_agp_buffer_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
|
||||
*
|
||||
* \sa drmAgpBind() and drmAgpUnbind().
|
||||
*/
|
||||
typedef struct drm_agp_binding {
|
||||
unsigned long handle; /**< From drm_agp_buffer */
|
||||
unsigned long handle; /**< From drm_agp_buffer */
|
||||
unsigned long offset; /**< In bytes -- will round to page boundary */
|
||||
} drm_agp_binding_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_INFO ioctl argument type.
|
||||
*
|
||||
|
@ -574,20 +533,19 @@ typedef struct drm_agp_binding {
|
|||
* drmAgpVendorId() and drmAgpDeviceId().
|
||||
*/
|
||||
typedef struct drm_agp_info {
|
||||
int agp_version_major;
|
||||
int agp_version_minor;
|
||||
unsigned long mode;
|
||||
unsigned long aperture_base; /* physical address */
|
||||
unsigned long aperture_size; /* bytes */
|
||||
unsigned long memory_allowed; /* bytes */
|
||||
unsigned long memory_used;
|
||||
int agp_version_major;
|
||||
int agp_version_minor;
|
||||
unsigned long mode;
|
||||
unsigned long aperture_base; /* physical address */
|
||||
unsigned long aperture_size; /* bytes */
|
||||
unsigned long memory_allowed; /* bytes */
|
||||
unsigned long memory_used;
|
||||
|
||||
/* PCI information */
|
||||
/* PCI information */
|
||||
unsigned short id_vendor;
|
||||
unsigned short id_device;
|
||||
} drm_agp_info_t;
|
||||
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_SG_ALLOC ioctl argument type.
|
||||
*/
|
||||
|
@ -606,7 +564,6 @@ typedef struct drm_set_version {
|
|||
int drm_dd_minor;
|
||||
} drm_set_version_t;
|
||||
|
||||
|
||||
#define DRM_IOCTL_BASE 'd'
|
||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* \file drm_agpsupport.h
|
||||
* \file drm_agpsupport.h
|
||||
* DRM support for AGP/GART backend
|
||||
*
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
@ -48,30 +48,31 @@
|
|||
* Verifies the AGP device has been initialized and acquired and fills in the
|
||||
* drm_agp_info structure with the information in drm_agp_head::agp_info.
|
||||
*/
|
||||
int drm_agp_info(drm_device_t *dev, drm_agp_info_t *info)
|
||||
int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info)
|
||||
{
|
||||
DRM_AGP_KERN *kern;
|
||||
DRM_AGP_KERN *kern;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return -EINVAL;
|
||||
|
||||
kern = &dev->agp->agp_info;
|
||||
kern = &dev->agp->agp_info;
|
||||
info->agp_version_major = kern->version.major;
|
||||
info->agp_version_minor = kern->version.minor;
|
||||
info->mode = kern->mode;
|
||||
info->aperture_base = kern->aper_base;
|
||||
info->aperture_size = kern->aper_size * 1024 * 1024;
|
||||
info->memory_allowed = kern->max_memory << PAGE_SHIFT;
|
||||
info->memory_used = kern->current_memory << PAGE_SHIFT;
|
||||
info->id_vendor = kern->device->vendor;
|
||||
info->id_device = kern->device->device;
|
||||
info->mode = kern->mode;
|
||||
info->aperture_base = kern->aper_base;
|
||||
info->aperture_size = kern->aper_size * 1024 * 1024;
|
||||
info->memory_allowed = kern->max_memory << PAGE_SHIFT;
|
||||
info->memory_used = kern->current_memory << PAGE_SHIFT;
|
||||
info->id_vendor = kern->device->vendor;
|
||||
info->id_device = kern->device->device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_agp_info);
|
||||
|
||||
int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
@ -81,7 +82,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
|
|||
err = drm_agp_info(dev, &info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
@ -91,12 +92,12 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
|
|||
* Acquire the AGP device.
|
||||
*
|
||||
* \param dev DRM device that is to acquire AGP
|
||||
* \return zero on success or a negative number on failure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Verifies the AGP device hasn't been acquired before and calls
|
||||
* \c agp_backend_acquire.
|
||||
*/
|
||||
int drm_agp_acquire(drm_device_t *dev)
|
||||
int drm_agp_acquire(drm_device_t * dev)
|
||||
{
|
||||
if (!dev->agp)
|
||||
return -ENODEV;
|
||||
|
@ -107,6 +108,7 @@ int drm_agp_acquire(drm_device_t *dev)
|
|||
dev->agp->acquired = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_agp_acquire);
|
||||
|
||||
/**
|
||||
|
@ -125,8 +127,8 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
|
|||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
|
||||
return drm_agp_acquire( (drm_device_t *) priv->head->dev );
|
||||
|
||||
return drm_agp_acquire((drm_device_t *) priv->head->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,7 +139,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
|
|||
*
|
||||
* Verifies the AGP device has been acquired and calls \c agp_backend_release.
|
||||
*/
|
||||
int drm_agp_release(drm_device_t *dev)
|
||||
int drm_agp_release(drm_device_t * dev)
|
||||
{
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return -EINVAL;
|
||||
|
@ -145,6 +147,7 @@ int drm_agp_release(drm_device_t *dev)
|
|||
dev->agp->acquired = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_agp_release);
|
||||
|
||||
int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
|
||||
|
@ -152,13 +155,13 @@ int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
|
|||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
||||
|
||||
return drm_agp_release(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the AGP bus.
|
||||
*
|
||||
*
|
||||
* \param dev DRM device that has previously acquired AGP.
|
||||
* \param mode Requested AGP mode.
|
||||
* \return zero on success or a negative number on failure.
|
||||
|
@ -166,27 +169,27 @@ int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
|
|||
* Verifies the AGP device has been acquired but not enabled, and calls
|
||||
* \c agp_enable.
|
||||
*/
|
||||
int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
|
||||
int drm_agp_enable(drm_device_t * dev, drm_agp_mode_t mode)
|
||||
{
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return -EINVAL;
|
||||
|
||||
dev->agp->mode = mode.mode;
|
||||
dev->agp->mode = mode.mode;
|
||||
agp_enable(dev->agp->bridge, mode.mode);
|
||||
dev->agp->base = dev->agp->agp_info.aper_base;
|
||||
dev->agp->base = dev->agp->agp_info.aper_base;
|
||||
dev->agp->enabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_agp_enable);
|
||||
|
||||
int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_agp_mode_t mode;
|
||||
|
||||
|
||||
if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -201,20 +204,20 @@ int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
|
|||
* \param cmd command.
|
||||
* \param arg pointer to a drm_agp_buffer structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
*
|
||||
* Verifies the AGP device is present and has been acquired, allocates the
|
||||
* memory via alloc_agp() and creates a drm_agp_mem entry for it.
|
||||
*/
|
||||
int drm_agp_alloc(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_agp_buffer_t request;
|
||||
drm_agp_mem_t *entry;
|
||||
DRM_AGP_MEM *memory;
|
||||
unsigned long pages;
|
||||
u32 type;
|
||||
drm_agp_mem_t *entry;
|
||||
DRM_AGP_MEM *memory;
|
||||
unsigned long pages;
|
||||
u32 type;
|
||||
drm_agp_buffer_t __user *argp = (void __user *)arg;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
|
@ -224,7 +227,7 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
|
|||
if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
|
||||
return -ENOMEM;
|
||||
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
|
||||
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
type = (u32) request.type;
|
||||
|
@ -234,21 +237,21 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
entry->handle = (unsigned long)memory->key + 1;
|
||||
entry->memory = memory;
|
||||
entry->bound = 0;
|
||||
entry->pages = pages;
|
||||
entry->prev = NULL;
|
||||
entry->next = dev->agp->memory;
|
||||
entry->handle = (unsigned long)memory->key + 1;
|
||||
entry->memory = memory;
|
||||
entry->bound = 0;
|
||||
entry->pages = pages;
|
||||
entry->prev = NULL;
|
||||
entry->next = dev->agp->memory;
|
||||
if (dev->agp->memory)
|
||||
dev->agp->memory->prev = entry;
|
||||
dev->agp->memory = entry;
|
||||
|
||||
request.handle = entry->handle;
|
||||
request.handle = entry->handle;
|
||||
request.physical = memory->physical;
|
||||
|
||||
if (copy_to_user(argp, &request, sizeof(request))) {
|
||||
dev->agp->memory = entry->next;
|
||||
dev->agp->memory = entry->next;
|
||||
dev->agp->memory->prev = NULL;
|
||||
drm_free_agp(memory, pages);
|
||||
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
|
||||
|
@ -263,11 +266,11 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
|
|||
* \param dev DRM device structure.
|
||||
* \param handle AGP memory handle.
|
||||
* \return pointer to the drm_agp_mem structure associated with \p handle.
|
||||
*
|
||||
*
|
||||
* Walks through drm_agp_head::memory until finding a matching handle.
|
||||
*/
|
||||
static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev,
|
||||
unsigned long handle)
|
||||
static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
|
||||
unsigned long handle)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
|
||||
|
@ -291,17 +294,18 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev,
|
|||
* entry and passes it to the unbind_agp() function.
|
||||
*/
|
||||
int drm_agp_unbind(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_agp_binding_t request;
|
||||
drm_agp_mem_t *entry;
|
||||
drm_agp_mem_t *entry;
|
||||
int ret;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&request, (drm_agp_binding_t __user *)arg, sizeof(request)))
|
||||
if (copy_from_user
|
||||
(&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
|
||||
return -EFAULT;
|
||||
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
|
||||
return -EINVAL;
|
||||
|
@ -309,7 +313,7 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
|
|||
return -EINVAL;
|
||||
ret = drm_unbind_agp(entry->memory);
|
||||
if (ret == 0)
|
||||
entry->bound = 0;
|
||||
entry->bound = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -327,18 +331,19 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
|
|||
* it to bind_agp() function.
|
||||
*/
|
||||
int drm_agp_bind(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_agp_binding_t request;
|
||||
drm_agp_mem_t *entry;
|
||||
int retcode;
|
||||
int page;
|
||||
drm_agp_mem_t *entry;
|
||||
int retcode;
|
||||
int page;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&request, (drm_agp_binding_t __user *)arg, sizeof(request)))
|
||||
if (copy_from_user
|
||||
(&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
|
||||
return -EFAULT;
|
||||
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
|
||||
return -EINVAL;
|
||||
|
@ -368,16 +373,17 @@ int drm_agp_bind(struct inode *inode, struct file *filp,
|
|||
* and unlinks from the doubly linked list it's inserted in.
|
||||
*/
|
||||
int drm_agp_free(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_agp_buffer_t request;
|
||||
drm_agp_mem_t *entry;
|
||||
drm_agp_mem_t *entry;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&request, (drm_agp_buffer_t __user *)arg, sizeof(request)))
|
||||
if (copy_from_user
|
||||
(&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
|
||||
return -EFAULT;
|
||||
if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
|
||||
return -EINVAL;
|
||||
|
@ -403,9 +409,9 @@ int drm_agp_free(struct inode *inode, struct file *filp,
|
|||
* \return pointer to a drm_agp_head structure.
|
||||
*
|
||||
*/
|
||||
drm_agp_head_t *drm_agp_init(drm_device_t *dev)
|
||||
drm_agp_head_t *drm_agp_init(drm_device_t * dev)
|
||||
{
|
||||
drm_agp_head_t *head = NULL;
|
||||
drm_agp_head_t *head = NULL;
|
||||
|
||||
if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
|
||||
return NULL;
|
||||
|
@ -433,13 +439,14 @@ drm_agp_head_t *drm_agp_init(drm_device_t *dev)
|
|||
}
|
||||
|
||||
/** Calls agp_allocate_memory() */
|
||||
DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type)
|
||||
DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge,
|
||||
size_t pages, u32 type)
|
||||
{
|
||||
return agp_allocate_memory(bridge, pages, type);
|
||||
}
|
||||
|
||||
/** Calls agp_free_memory() */
|
||||
int drm_agp_free_memory(DRM_AGP_MEM *handle)
|
||||
int drm_agp_free_memory(DRM_AGP_MEM * handle)
|
||||
{
|
||||
if (!handle)
|
||||
return 0;
|
||||
|
@ -448,20 +455,21 @@ int drm_agp_free_memory(DRM_AGP_MEM *handle)
|
|||
}
|
||||
|
||||
/** Calls agp_bind_memory() */
|
||||
int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start)
|
||||
int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start)
|
||||
{
|
||||
if (!handle)
|
||||
return -EINVAL;
|
||||
return agp_bind_memory(handle, start);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_agp_bind_memory);
|
||||
|
||||
/** Calls agp_unbind_memory() */
|
||||
int drm_agp_unbind_memory(DRM_AGP_MEM *handle)
|
||||
int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
|
||||
{
|
||||
if (!handle)
|
||||
return -EINVAL;
|
||||
return agp_unbind_memory(handle);
|
||||
}
|
||||
|
||||
#endif /* __OS_HAS_AGP */
|
||||
#endif /* __OS_HAS_AGP */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_auth.h
|
||||
* \file drm_auth.c
|
||||
* IOCTLs for authentication
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -46,7 +46,7 @@
|
|||
*/
|
||||
static int drm_hash_magic(drm_magic_t magic)
|
||||
{
|
||||
return magic & (DRM_HASH_SIZE-1);
|
||||
return magic & (DRM_HASH_SIZE - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,11 +59,11 @@ static int drm_hash_magic(drm_magic_t magic)
|
|||
* the one with matching magic number, while holding the drm_device::struct_sem
|
||||
* lock.
|
||||
*/
|
||||
static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
|
||||
static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
|
||||
{
|
||||
drm_file_t *retval = NULL;
|
||||
drm_file_t *retval = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash = drm_hash_magic(magic);
|
||||
int hash = drm_hash_magic(magic);
|
||||
|
||||
down(&dev->struct_sem);
|
||||
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
|
||||
|
@ -78,7 +78,7 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
|
|||
|
||||
/**
|
||||
* Adds a magic number.
|
||||
*
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param priv file private data.
|
||||
* \param magic magic number.
|
||||
|
@ -87,28 +87,30 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
|
|||
* associated the magic number hash key in drm_device::magiclist, while holding
|
||||
* the drm_device::struct_sem lock.
|
||||
*/
|
||||
static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
|
||||
static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
|
||||
drm_magic_t magic)
|
||||
{
|
||||
int hash;
|
||||
int hash;
|
||||
drm_magic_entry_t *entry;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
hash = drm_hash_magic(magic);
|
||||
entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
|
||||
if (!entry) return -ENOMEM;
|
||||
hash = drm_hash_magic(magic);
|
||||
entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
entry->magic = magic;
|
||||
entry->priv = priv;
|
||||
entry->next = NULL;
|
||||
entry->priv = priv;
|
||||
entry->next = NULL;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
if (dev->magiclist[hash].tail) {
|
||||
dev->magiclist[hash].tail->next = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
} else {
|
||||
dev->magiclist[hash].head = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
dev->magiclist[hash].head = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
|
||||
|
@ -117,19 +119,18 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
|
|||
|
||||
/**
|
||||
* Remove a magic number.
|
||||
*
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param magic magic number.
|
||||
*
|
||||
* Searches and unlinks the entry in drm_device::magiclist with the magic
|
||||
* number hash key, while holding the drm_device::struct_sem lock.
|
||||
*/
|
||||
static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
|
||||
static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
|
||||
{
|
||||
drm_magic_entry_t *prev = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash;
|
||||
|
||||
int hash;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
hash = drm_hash_magic(magic);
|
||||
|
@ -171,21 +172,22 @@ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
|
|||
* filp.
|
||||
*/
|
||||
int drm_getmagic(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
static drm_magic_t sequence = 0;
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_auth_t auth;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_auth_t auth;
|
||||
|
||||
/* Find unique magic */
|
||||
/* Find unique magic */
|
||||
if (priv->magic) {
|
||||
auth.magic = priv->magic;
|
||||
} else {
|
||||
do {
|
||||
spin_lock(&lock);
|
||||
if (!sequence) ++sequence; /* reserve 0 */
|
||||
if (!sequence)
|
||||
++sequence; /* reserve 0 */
|
||||
auth.magic = sequence++;
|
||||
spin_unlock(&lock);
|
||||
} while (drm_find_file(dev, auth.magic));
|
||||
|
@ -194,7 +196,7 @@ int drm_getmagic(struct inode *inode, struct file *filp,
|
|||
}
|
||||
|
||||
DRM_DEBUG("%u\n", auth.magic);
|
||||
if (copy_to_user((drm_auth_t __user *)arg, &auth, sizeof(auth)))
|
||||
if (copy_to_user((drm_auth_t __user *) arg, &auth, sizeof(auth)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -211,14 +213,14 @@ int drm_getmagic(struct inode *inode, struct file *filp,
|
|||
* Checks if \p filp is associated with the magic number passed in \arg.
|
||||
*/
|
||||
int drm_authmagic(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_auth_t auth;
|
||||
drm_file_t *file;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_auth_t auth;
|
||||
drm_file_t *file;
|
||||
|
||||
if (copy_from_user(&auth, (drm_auth_t __user *)arg, sizeof(auth)))
|
||||
if (copy_from_user(&auth, (drm_auth_t __user *) arg, sizeof(auth)))
|
||||
return -EFAULT;
|
||||
DRM_DEBUG("%u\n", auth.magic);
|
||||
if ((file = drm_find_file(dev, auth.magic))) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* \file drm_context.h
|
||||
* \file drm_context.c
|
||||
* IOCTLs for generic contexts
|
||||
*
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
@ -56,25 +56,26 @@
|
|||
* in drm_device::context_sareas, while holding the drm_device::struct_sem
|
||||
* lock.
|
||||
*/
|
||||
void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle )
|
||||
void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
|
||||
{
|
||||
if ( ctx_handle < 0 ) goto failed;
|
||||
if ( !dev->ctx_bitmap ) goto failed;
|
||||
if (ctx_handle < 0)
|
||||
goto failed;
|
||||
if (!dev->ctx_bitmap)
|
||||
goto failed;
|
||||
|
||||
if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
|
||||
if (ctx_handle < DRM_MAX_CTXBITMAP) {
|
||||
down(&dev->struct_sem);
|
||||
clear_bit( ctx_handle, dev->ctx_bitmap );
|
||||
clear_bit(ctx_handle, dev->ctx_bitmap);
|
||||
dev->context_sareas[ctx_handle] = NULL;
|
||||
up(&dev->struct_sem);
|
||||
return;
|
||||
}
|
||||
failed:
|
||||
DRM_ERROR( "Attempt to free invalid context handle: %d\n",
|
||||
ctx_handle );
|
||||
return;
|
||||
failed:
|
||||
DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Context bitmap allocation.
|
||||
*
|
||||
* \param dev DRM device.
|
||||
|
@ -84,29 +85,33 @@ failed:
|
|||
* drm_device::context_sareas to accommodate the new entry while holding the
|
||||
* drm_device::struct_sem lock.
|
||||
*/
|
||||
static int drm_ctxbitmap_next( drm_device_t *dev )
|
||||
static int drm_ctxbitmap_next(drm_device_t * dev)
|
||||
{
|
||||
int bit;
|
||||
|
||||
if(!dev->ctx_bitmap) return -1;
|
||||
if (!dev->ctx_bitmap)
|
||||
return -1;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
|
||||
if ( bit < DRM_MAX_CTXBITMAP ) {
|
||||
set_bit( bit, dev->ctx_bitmap );
|
||||
DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit );
|
||||
if((bit+1) > dev->max_context) {
|
||||
dev->max_context = (bit+1);
|
||||
if(dev->context_sareas) {
|
||||
bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
|
||||
if (bit < DRM_MAX_CTXBITMAP) {
|
||||
set_bit(bit, dev->ctx_bitmap);
|
||||
DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
|
||||
if ((bit + 1) > dev->max_context) {
|
||||
dev->max_context = (bit + 1);
|
||||
if (dev->context_sareas) {
|
||||
drm_map_t **ctx_sareas;
|
||||
|
||||
ctx_sareas = drm_realloc(dev->context_sareas,
|
||||
(dev->max_context - 1) *
|
||||
sizeof(*dev->context_sareas),
|
||||
dev->max_context *
|
||||
sizeof(*dev->context_sareas),
|
||||
DRM_MEM_MAPS);
|
||||
if(!ctx_sareas) {
|
||||
(dev->max_context -
|
||||
1) *
|
||||
sizeof(*dev->
|
||||
context_sareas),
|
||||
dev->max_context *
|
||||
sizeof(*dev->
|
||||
context_sareas),
|
||||
DRM_MEM_MAPS);
|
||||
if (!ctx_sareas) {
|
||||
clear_bit(bit, dev->ctx_bitmap);
|
||||
up(&dev->struct_sem);
|
||||
return -1;
|
||||
|
@ -115,11 +120,11 @@ static int drm_ctxbitmap_next( drm_device_t *dev )
|
|||
dev->context_sareas[bit] = NULL;
|
||||
} else {
|
||||
/* max_context == 1 at this point */
|
||||
dev->context_sareas = drm_alloc(
|
||||
dev->max_context *
|
||||
sizeof(*dev->context_sareas),
|
||||
DRM_MEM_MAPS);
|
||||
if(!dev->context_sareas) {
|
||||
dev->context_sareas =
|
||||
drm_alloc(dev->max_context *
|
||||
sizeof(*dev->context_sareas),
|
||||
DRM_MEM_MAPS);
|
||||
if (!dev->context_sareas) {
|
||||
clear_bit(bit, dev->ctx_bitmap);
|
||||
up(&dev->struct_sem);
|
||||
return -1;
|
||||
|
@ -142,26 +147,26 @@ static int drm_ctxbitmap_next( drm_device_t *dev )
|
|||
* Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
|
||||
* the drm_device::struct_sem lock.
|
||||
*/
|
||||
int drm_ctxbitmap_init( drm_device_t *dev )
|
||||
int drm_ctxbitmap_init(drm_device_t * dev)
|
||||
{
|
||||
int i;
|
||||
int temp;
|
||||
int temp;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
dev->ctx_bitmap = (unsigned long *) drm_alloc( PAGE_SIZE,
|
||||
DRM_MEM_CTXBITMAP );
|
||||
if ( dev->ctx_bitmap == NULL ) {
|
||||
dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
|
||||
DRM_MEM_CTXBITMAP);
|
||||
if (dev->ctx_bitmap == NULL) {
|
||||
up(&dev->struct_sem);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
|
||||
memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
|
||||
dev->context_sareas = NULL;
|
||||
dev->max_context = -1;
|
||||
up(&dev->struct_sem);
|
||||
|
||||
for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
|
||||
temp = drm_ctxbitmap_next( dev );
|
||||
DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
|
||||
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
|
||||
temp = drm_ctxbitmap_next(dev);
|
||||
DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -175,14 +180,14 @@ int drm_ctxbitmap_init( drm_device_t *dev )
|
|||
* Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
|
||||
* the drm_device::struct_sem lock.
|
||||
*/
|
||||
void drm_ctxbitmap_cleanup( drm_device_t *dev )
|
||||
void drm_ctxbitmap_cleanup(drm_device_t * dev)
|
||||
{
|
||||
down(&dev->struct_sem);
|
||||
if( dev->context_sareas ) drm_free( dev->context_sareas,
|
||||
sizeof(*dev->context_sareas) *
|
||||
dev->max_context,
|
||||
DRM_MEM_MAPS );
|
||||
drm_free( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
|
||||
if (dev->context_sareas)
|
||||
drm_free(dev->context_sareas,
|
||||
sizeof(*dev->context_sareas) *
|
||||
dev->max_context, DRM_MEM_MAPS);
|
||||
drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
|
||||
up(&dev->struct_sem);
|
||||
}
|
||||
|
||||
|
@ -194,7 +199,7 @@ void drm_ctxbitmap_cleanup( drm_device_t *dev )
|
|||
|
||||
/**
|
||||
* Get per-context SAREA.
|
||||
*
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
|
@ -205,10 +210,10 @@ void drm_ctxbitmap_cleanup( drm_device_t *dev )
|
|||
* returns its handle.
|
||||
*/
|
||||
int drm_getsareactx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_ctx_priv_map_t __user *argp = (void __user *)arg;
|
||||
drm_ctx_priv_map_t request;
|
||||
drm_map_t *map;
|
||||
|
@ -218,7 +223,8 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
|
|||
return -EFAULT;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
|
||||
if (dev->max_context < 0
|
||||
|| request.ctx_id >= (unsigned)dev->max_context) {
|
||||
up(&dev->struct_sem);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -226,17 +232,17 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
|
|||
map = dev->context_sareas[request.ctx_id];
|
||||
up(&dev->struct_sem);
|
||||
|
||||
request.handle = 0;
|
||||
list_for_each_entry(_entry, &dev->maplist->head,head) {
|
||||
request.handle = NULL;
|
||||
list_for_each_entry(_entry, &dev->maplist->head, head) {
|
||||
if (_entry->map == map) {
|
||||
request.handle = (void *)(unsigned long)_entry->user_token;
|
||||
request.handle =
|
||||
(void *)(unsigned long)_entry->user_token;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (request.handle == 0)
|
||||
if (request.handle == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
if (copy_to_user(argp, &request, sizeof(request)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
@ -244,7 +250,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
|
|||
|
||||
/**
|
||||
* Set per-context SAREA.
|
||||
*
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
|
@ -255,37 +261,37 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
|
|||
* drm_device::context_sareas with it.
|
||||
*/
|
||||
int drm_setsareactx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_ctx_priv_map_t request;
|
||||
drm_map_t *map = NULL;
|
||||
drm_map_list_t *r_list = NULL;
|
||||
struct list_head *list;
|
||||
|
||||
if (copy_from_user(&request,
|
||||
(drm_ctx_priv_map_t __user *)arg,
|
||||
sizeof(request)))
|
||||
(drm_ctx_priv_map_t __user *) arg, sizeof(request)))
|
||||
return -EFAULT;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
if (r_list->map
|
||||
&& r_list->user_token == (unsigned long) request.handle)
|
||||
&& r_list->user_token == (unsigned long)request.handle)
|
||||
goto found;
|
||||
}
|
||||
bad:
|
||||
bad:
|
||||
up(&dev->struct_sem);
|
||||
return -EINVAL;
|
||||
|
||||
found:
|
||||
found:
|
||||
map = r_list->map;
|
||||
if (!map) goto bad;
|
||||
if (!map)
|
||||
goto bad;
|
||||
if (dev->max_context < 0)
|
||||
goto bad;
|
||||
if (request.ctx_id >= (unsigned) dev->max_context)
|
||||
if (request.ctx_id >= (unsigned)dev->max_context)
|
||||
goto bad;
|
||||
dev->context_sareas[request.ctx_id] = map;
|
||||
up(&dev->struct_sem);
|
||||
|
@ -308,22 +314,21 @@ found:
|
|||
*
|
||||
* Attempt to set drm_device::context_flag.
|
||||
*/
|
||||
static int drm_context_switch( drm_device_t *dev, int old, int new )
|
||||
static int drm_context_switch(drm_device_t * dev, int old, int new)
|
||||
{
|
||||
if ( test_and_set_bit( 0, &dev->context_flag ) ) {
|
||||
DRM_ERROR( "Reentering -- FIXME\n" );
|
||||
return -EBUSY;
|
||||
}
|
||||
if (test_and_set_bit(0, &dev->context_flag)) {
|
||||
DRM_ERROR("Reentering -- FIXME\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
DRM_DEBUG("Context switch from %d to %d\n", old, new);
|
||||
|
||||
DRM_DEBUG( "Context switch from %d to %d\n", old, new );
|
||||
if (new == dev->last_context) {
|
||||
clear_bit(0, &dev->context_flag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( new == dev->last_context ) {
|
||||
clear_bit( 0, &dev->context_flag );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -337,22 +342,22 @@ static int drm_context_switch( drm_device_t *dev, int old, int new )
|
|||
* hardware lock is held, clears the drm_device::context_flag and wakes up
|
||||
* drm_device::context_wait.
|
||||
*/
|
||||
static int drm_context_switch_complete( drm_device_t *dev, int new )
|
||||
static int drm_context_switch_complete(drm_device_t * dev, int new)
|
||||
{
|
||||
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
|
||||
dev->last_switch = jiffies;
|
||||
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
|
||||
dev->last_switch = jiffies;
|
||||
|
||||
if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
|
||||
DRM_ERROR( "Lock isn't held after context switch\n" );
|
||||
}
|
||||
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
|
||||
DRM_ERROR("Lock isn't held after context switch\n");
|
||||
}
|
||||
|
||||
/* If a context switch is ever initiated
|
||||
when the kernel holds the lock, release
|
||||
that lock here. */
|
||||
clear_bit( 0, &dev->context_flag );
|
||||
wake_up( &dev->context_wait );
|
||||
/* If a context switch is ever initiated
|
||||
when the kernel holds the lock, release
|
||||
that lock here. */
|
||||
clear_bit(0, &dev->context_flag);
|
||||
wake_up(&dev->context_wait);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -364,29 +369,28 @@ static int drm_context_switch_complete( drm_device_t *dev, int new )
|
|||
* \param arg user argument pointing to a drm_ctx_res structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*/
|
||||
int drm_resctx( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_resctx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_ctx_res_t res;
|
||||
drm_ctx_t __user *argp = (void __user *)arg;
|
||||
drm_ctx_t ctx;
|
||||
int i;
|
||||
|
||||
if ( copy_from_user( &res, argp, sizeof(res) ) )
|
||||
if (copy_from_user(&res, argp, sizeof(res)))
|
||||
return -EFAULT;
|
||||
|
||||
if ( res.count >= DRM_RESERVED_CONTEXTS ) {
|
||||
memset( &ctx, 0, sizeof(ctx) );
|
||||
for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
|
||||
if (res.count >= DRM_RESERVED_CONTEXTS) {
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
|
||||
ctx.handle = i;
|
||||
if ( copy_to_user( &res.contexts[i],
|
||||
&ctx, sizeof(ctx) ) )
|
||||
if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
res.count = DRM_RESERVED_CONTEXTS;
|
||||
|
||||
if ( copy_to_user( argp, &res, sizeof(res) ) )
|
||||
if (copy_to_user(argp, &res, sizeof(res)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -402,58 +406,57 @@ int drm_resctx( struct inode *inode, struct file *filp,
|
|||
*
|
||||
* Get a new handle for the context and copy to userspace.
|
||||
*/
|
||||
int drm_addctx( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_addctx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_ctx_list_t * ctx_entry;
|
||||
drm_ctx_list_t *ctx_entry;
|
||||
drm_ctx_t __user *argp = (void __user *)arg;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
|
||||
if (copy_from_user(&ctx, argp, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
|
||||
ctx.handle = drm_ctxbitmap_next( dev );
|
||||
if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
|
||||
/* Skip kernel's context and get a new one. */
|
||||
ctx.handle = drm_ctxbitmap_next( dev );
|
||||
ctx.handle = drm_ctxbitmap_next(dev);
|
||||
if (ctx.handle == DRM_KERNEL_CONTEXT) {
|
||||
/* Skip kernel's context and get a new one. */
|
||||
ctx.handle = drm_ctxbitmap_next(dev);
|
||||
}
|
||||
DRM_DEBUG( "%d\n", ctx.handle );
|
||||
if ( ctx.handle == -1 ) {
|
||||
DRM_DEBUG( "Not enough free contexts.\n" );
|
||||
/* Should this return -EBUSY instead? */
|
||||
DRM_DEBUG("%d\n", ctx.handle);
|
||||
if (ctx.handle == -1) {
|
||||
DRM_DEBUG("Not enough free contexts.\n");
|
||||
/* Should this return -EBUSY instead? */
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ( ctx.handle != DRM_KERNEL_CONTEXT )
|
||||
{
|
||||
if (ctx.handle != DRM_KERNEL_CONTEXT) {
|
||||
if (dev->driver->context_ctor)
|
||||
dev->driver->context_ctor(dev, ctx.handle);
|
||||
}
|
||||
|
||||
ctx_entry = drm_alloc( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
|
||||
if ( !ctx_entry ) {
|
||||
ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST);
|
||||
if (!ctx_entry) {
|
||||
DRM_DEBUG("out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD( &ctx_entry->head );
|
||||
INIT_LIST_HEAD(&ctx_entry->head);
|
||||
ctx_entry->handle = ctx.handle;
|
||||
ctx_entry->tag = priv;
|
||||
|
||||
down( &dev->ctxlist_sem );
|
||||
list_add( &ctx_entry->head, &dev->ctxlist->head );
|
||||
down(&dev->ctxlist_sem);
|
||||
list_add(&ctx_entry->head, &dev->ctxlist->head);
|
||||
++dev->ctx_count;
|
||||
up( &dev->ctxlist_sem );
|
||||
up(&dev->ctxlist_sem);
|
||||
|
||||
if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
|
||||
if (copy_to_user(argp, &ctx, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_modctx( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_modctx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
/* This does nothing */
|
||||
return 0;
|
||||
|
@ -468,19 +471,19 @@ int drm_modctx( struct inode *inode, struct file *filp,
|
|||
* \param arg user argument pointing to a drm_ctx structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*/
|
||||
int drm_getctx( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_getctx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_ctx_t __user *argp = (void __user *)arg;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
if ( copy_from_user( &ctx, argp, sizeof(ctx) ) )
|
||||
if (copy_from_user(&ctx, argp, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
|
||||
/* This is 0, because we don't handle any context flags */
|
||||
ctx.flags = 0;
|
||||
|
||||
if ( copy_to_user( argp, &ctx, sizeof(ctx) ) )
|
||||
if (copy_to_user(argp, &ctx, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -496,18 +499,18 @@ int drm_getctx( struct inode *inode, struct file *filp,
|
|||
*
|
||||
* Calls context_switch().
|
||||
*/
|
||||
int drm_switchctx( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_switchctx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
|
||||
DRM_DEBUG( "%d\n", ctx.handle );
|
||||
return drm_context_switch( dev, dev->last_context, ctx.handle );
|
||||
DRM_DEBUG("%d\n", ctx.handle);
|
||||
return drm_context_switch(dev, dev->last_context, ctx.handle);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -521,18 +524,18 @@ int drm_switchctx( struct inode *inode, struct file *filp,
|
|||
*
|
||||
* Calls context_switch_complete().
|
||||
*/
|
||||
int drm_newctx( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_newctx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
|
||||
DRM_DEBUG( "%d\n", ctx.handle );
|
||||
drm_context_switch_complete( dev, ctx.handle );
|
||||
DRM_DEBUG("%d\n", ctx.handle);
|
||||
drm_context_switch_complete(dev, ctx.handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -548,42 +551,41 @@ int drm_newctx( struct inode *inode, struct file *filp,
|
|||
*
|
||||
* If not the special kernel context, calls ctxbitmap_free() to free the specified context.
|
||||
*/
|
||||
int drm_rmctx( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_rmctx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
|
||||
DRM_DEBUG( "%d\n", ctx.handle );
|
||||
if ( ctx.handle == DRM_KERNEL_CONTEXT + 1 ) {
|
||||
DRM_DEBUG("%d\n", ctx.handle);
|
||||
if (ctx.handle == DRM_KERNEL_CONTEXT + 1) {
|
||||
priv->remove_auth_on_close = 1;
|
||||
}
|
||||
if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
|
||||
if (ctx.handle != DRM_KERNEL_CONTEXT) {
|
||||
if (dev->driver->context_dtor)
|
||||
dev->driver->context_dtor(dev, ctx.handle);
|
||||
drm_ctxbitmap_free( dev, ctx.handle );
|
||||
drm_ctxbitmap_free(dev, ctx.handle);
|
||||
}
|
||||
|
||||
down( &dev->ctxlist_sem );
|
||||
if ( !list_empty( &dev->ctxlist->head ) ) {
|
||||
down(&dev->ctxlist_sem);
|
||||
if (!list_empty(&dev->ctxlist->head)) {
|
||||
drm_ctx_list_t *pos, *n;
|
||||
|
||||
list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
|
||||
if ( pos->handle == ctx.handle ) {
|
||||
list_del( &pos->head );
|
||||
drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
|
||||
list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
|
||||
if (pos->handle == ctx.handle) {
|
||||
list_del(&pos->head);
|
||||
drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
|
||||
--dev->ctx_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
up( &dev->ctxlist_sem );
|
||||
up(&dev->ctxlist_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_dma.h
|
||||
* \file drm_dma.c
|
||||
* DMA IOCTL and function support
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -37,23 +37,23 @@
|
|||
|
||||
/**
|
||||
* Initialize the DMA data.
|
||||
*
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \return zero on success or a negative value on failure.
|
||||
*
|
||||
* Allocate and initialize a drm_device_dma structure.
|
||||
*/
|
||||
int drm_dma_setup( drm_device_t *dev )
|
||||
int drm_dma_setup(drm_device_t * dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
dev->dma = drm_alloc( sizeof(*dev->dma), DRM_MEM_DRIVER );
|
||||
if ( !dev->dma )
|
||||
dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER);
|
||||
if (!dev->dma)
|
||||
return -ENOMEM;
|
||||
|
||||
memset( dev->dma, 0, sizeof(*dev->dma) );
|
||||
memset(dev->dma, 0, sizeof(*dev->dma));
|
||||
|
||||
for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++)
|
||||
memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
|
||||
|
||||
return 0;
|
||||
|
@ -67,14 +67,15 @@ int drm_dma_setup( drm_device_t *dev )
|
|||
* Free all pages associated with DMA buffers, the buffers and pages lists, and
|
||||
* finally the the drm_device::dma structure itself.
|
||||
*/
|
||||
void drm_dma_takedown(drm_device_t *dev)
|
||||
void drm_dma_takedown(drm_device_t * dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i, j;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i, j;
|
||||
|
||||
if (!dma) return;
|
||||
if (!dma)
|
||||
return;
|
||||
|
||||
/* Clear dma buffers */
|
||||
/* Clear dma buffers */
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
if (dma->bufs[i].seg_count) {
|
||||
DRM_DEBUG("order %d: buf_count = %d,"
|
||||
|
@ -85,64 +86,63 @@ void drm_dma_takedown(drm_device_t *dev)
|
|||
for (j = 0; j < dma->bufs[i].seg_count; j++) {
|
||||
if (dma->bufs[i].seglist[j]) {
|
||||
drm_free_pages(dma->bufs[i].seglist[j],
|
||||
dma->bufs[i].page_order,
|
||||
DRM_MEM_DMA);
|
||||
dma->bufs[i].page_order,
|
||||
DRM_MEM_DMA);
|
||||
}
|
||||
}
|
||||
drm_free(dma->bufs[i].seglist,
|
||||
dma->bufs[i].seg_count
|
||||
* sizeof(*dma->bufs[0].seglist),
|
||||
DRM_MEM_SEGS);
|
||||
dma->bufs[i].seg_count
|
||||
* sizeof(*dma->bufs[0].seglist), DRM_MEM_SEGS);
|
||||
}
|
||||
if (dma->bufs[i].buf_count) {
|
||||
for (j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
if (dma->bufs[i].buf_count) {
|
||||
for (j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
if (dma->bufs[i].buflist[j].dev_private) {
|
||||
drm_free(dma->bufs[i].buflist[j].dev_private,
|
||||
dma->bufs[i].buflist[j].dev_priv_size,
|
||||
DRM_MEM_BUFS);
|
||||
drm_free(dma->bufs[i].buflist[j].
|
||||
dev_private,
|
||||
dma->bufs[i].buflist[j].
|
||||
dev_priv_size, DRM_MEM_BUFS);
|
||||
}
|
||||
}
|
||||
drm_free(dma->bufs[i].buflist,
|
||||
dma->bufs[i].buf_count *
|
||||
sizeof(*dma->bufs[0].buflist),
|
||||
DRM_MEM_BUFS);
|
||||
drm_free(dma->bufs[i].buflist,
|
||||
dma->bufs[i].buf_count *
|
||||
sizeof(*dma->bufs[0].buflist), DRM_MEM_BUFS);
|
||||
}
|
||||
}
|
||||
|
||||
if (dma->buflist) {
|
||||
drm_free(dma->buflist,
|
||||
dma->buf_count * sizeof(*dma->buflist),
|
||||
DRM_MEM_BUFS);
|
||||
dma->buf_count * sizeof(*dma->buflist), DRM_MEM_BUFS);
|
||||
}
|
||||
|
||||
if (dma->pagelist) {
|
||||
drm_free(dma->pagelist,
|
||||
dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
dma->page_count * sizeof(*dma->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
}
|
||||
drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
|
||||
dev->dma = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free a buffer.
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param buf buffer to free.
|
||||
*
|
||||
*
|
||||
* Resets the fields of \p buf.
|
||||
*/
|
||||
void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
|
||||
void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
|
||||
{
|
||||
if (!buf) return;
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
buf->waiting = 0;
|
||||
buf->pending = 0;
|
||||
buf->filp = NULL;
|
||||
buf->used = 0;
|
||||
buf->waiting = 0;
|
||||
buf->pending = 0;
|
||||
buf->filp = NULL;
|
||||
buf->used = 0;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && waitqueue_active(&buf->dma_wait)) {
|
||||
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)
|
||||
&& waitqueue_active(&buf->dma_wait)) {
|
||||
wake_up_interruptible(&buf->dma_wait);
|
||||
}
|
||||
}
|
||||
|
@ -154,12 +154,13 @@ void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
|
|||
*
|
||||
* Frees each buffer associated with \p filp not already on the hardware.
|
||||
*/
|
||||
void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp)
|
||||
void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (!dma) return;
|
||||
if (!dma)
|
||||
return;
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (dma->buflist[i]->filp == filp) {
|
||||
switch (dma->buflist[i]->list) {
|
||||
|
@ -176,5 +177,5 @@ void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp)
|
|||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_core_reclaim_buffers);
|
||||
|
||||
EXPORT_SYMBOL(drm_core_reclaim_buffers);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_drawable.h
|
||||
* \file drm_drawable.c
|
||||
* IOCTLs for drawables
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -37,20 +37,20 @@
|
|||
|
||||
/** No-op. */
|
||||
int drm_adddraw(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_draw_t draw;
|
||||
|
||||
draw.handle = 0; /* NOOP */
|
||||
DRM_DEBUG("%d\n", draw.handle);
|
||||
if (copy_to_user((drm_draw_t __user *)arg, &draw, sizeof(draw)))
|
||||
if (copy_to_user((drm_draw_t __user *) arg, &draw, sizeof(draw)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** No-op. */
|
||||
int drm_rmdraw(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return 0; /* NOOP */
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_drv.h
|
||||
* \file drm_drv.c
|
||||
* Generic driver template
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -55,67 +55,67 @@ static int drm_version(struct inode *inode, struct file *filp,
|
|||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
/** Ioctl table */
|
||||
static drm_ioctl_desc_t drm_ioctls[] = {
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_by_busid, 0, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { drm_getmap, 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { drm_getclient, 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { drm_getstats, 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { drm_setversion, 0, 1 },
|
||||
static drm_ioctl_desc_t drm_ioctls[] = {
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, 0, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, 0, 1},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_noop, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, 1, 1},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap_ioctl,1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap_ioctl, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, 1, 0},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, 1, 0},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { drm_addctx, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { drm_rmctx, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { drm_modctx, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { drm_getctx, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { drm_newctx, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { drm_resctx, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, 1, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, 1, 0},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, 1, 1},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { drm_lock, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { drm_unlock, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, 1, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, 1, 0},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_noop, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, 1, 0},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_addbufs, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_mapbufs, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, 1, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, 1, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, 1, 0},
|
||||
/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, 1, 1},
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire_ioctl, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release_ioctl, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable_ioctl, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info_ioctl, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, 1, 0},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind, 1, 1},
|
||||
#endif
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { drm_sg_alloc, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, 1, 1},
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, 1, 1},
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0, 0},
|
||||
};
|
||||
|
||||
#define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls )
|
||||
|
@ -129,17 +129,17 @@ static drm_ioctl_desc_t drm_ioctls[] = {
|
|||
*
|
||||
* \sa drm_device
|
||||
*/
|
||||
int drm_takedown( drm_device_t *dev )
|
||||
int drm_takedown(drm_device_t * dev)
|
||||
{
|
||||
drm_magic_entry_t *pt, *next;
|
||||
drm_map_list_t *r_list;
|
||||
drm_vma_entry_t *vma, *vma_next;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG( "\n" );
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (dev->driver->pretakedown)
|
||||
dev->driver->pretakedown(dev);
|
||||
dev->driver->pretakedown(dev);
|
||||
DRM_DEBUG("driver pretakedown completed\n");
|
||||
|
||||
if (dev->unique) {
|
||||
|
@ -148,95 +148,95 @@ int drm_takedown( drm_device_t *dev )
|
|||
dev->unique_len = 0;
|
||||
}
|
||||
|
||||
if ( dev->irq_enabled ) drm_irq_uninstall( dev );
|
||||
if (dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
down( &dev->struct_sem );
|
||||
del_timer( &dev->timer );
|
||||
down(&dev->struct_sem);
|
||||
del_timer(&dev->timer);
|
||||
|
||||
/* Clear pid list */
|
||||
for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
|
||||
for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
|
||||
/* Clear pid list */
|
||||
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
||||
for (pt = dev->magiclist[i].head; pt; pt = next) {
|
||||
next = pt->next;
|
||||
drm_free( pt, sizeof(*pt), DRM_MEM_MAGIC );
|
||||
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||
}
|
||||
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
|
||||
}
|
||||
|
||||
/* Clear AGP information */
|
||||
/* Clear AGP information */
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
drm_agp_mem_t *entry;
|
||||
drm_agp_mem_t *nexte;
|
||||
|
||||
/* Remove AGP resources, but leave dev->agp
|
||||
intact until drv_cleanup is called. */
|
||||
for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
|
||||
/* Remove AGP resources, but leave dev->agp
|
||||
intact until drv_cleanup is called. */
|
||||
for (entry = dev->agp->memory; entry; entry = nexte) {
|
||||
nexte = entry->next;
|
||||
if ( entry->bound ) drm_unbind_agp( entry->memory );
|
||||
drm_free_agp( entry->memory, entry->pages );
|
||||
drm_free( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
|
||||
if (entry->bound)
|
||||
drm_unbind_agp(entry->memory);
|
||||
drm_free_agp(entry->memory, entry->pages);
|
||||
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
|
||||
}
|
||||
dev->agp->memory = NULL;
|
||||
|
||||
if (dev->agp->acquired)
|
||||
drm_agp_release(dev);
|
||||
drm_agp_release(dev);
|
||||
|
||||
dev->agp->acquired = 0;
|
||||
dev->agp->enabled = 0;
|
||||
dev->agp->enabled = 0;
|
||||
}
|
||||
if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
|
||||
drm_sg_cleanup(dev->sg);
|
||||
dev->sg = NULL;
|
||||
}
|
||||
|
||||
/* Clear vma list (only built for debugging) */
|
||||
if ( dev->vmalist ) {
|
||||
for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
|
||||
/* Clear vma list (only built for debugging) */
|
||||
if (dev->vmalist) {
|
||||
for (vma = dev->vmalist; vma; vma = vma_next) {
|
||||
vma_next = vma->next;
|
||||
drm_free( vma, sizeof(*vma), DRM_MEM_VMAS );
|
||||
drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
|
||||
}
|
||||
dev->vmalist = NULL;
|
||||
}
|
||||
|
||||
if( dev->maplist ) {
|
||||
if (dev->maplist) {
|
||||
while (!list_empty(&dev->maplist->head)) {
|
||||
struct list_head *list = dev->maplist->head.next;
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
drm_rmmap_locked(dev, r_list->map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
|
||||
for ( i = 0 ; i < dev->queue_count ; i++ ) {
|
||||
if ( dev->queuelist[i] ) {
|
||||
drm_free( dev->queuelist[i],
|
||||
sizeof(*dev->queuelist[0]),
|
||||
DRM_MEM_QUEUES );
|
||||
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
|
||||
for (i = 0; i < dev->queue_count; i++) {
|
||||
if (dev->queuelist[i]) {
|
||||
drm_free(dev->queuelist[i],
|
||||
sizeof(*dev->queuelist[0]),
|
||||
DRM_MEM_QUEUES);
|
||||
dev->queuelist[i] = NULL;
|
||||
}
|
||||
}
|
||||
drm_free( dev->queuelist,
|
||||
dev->queue_slots * sizeof(*dev->queuelist),
|
||||
DRM_MEM_QUEUES );
|
||||
drm_free(dev->queuelist,
|
||||
dev->queue_slots * sizeof(*dev->queuelist),
|
||||
DRM_MEM_QUEUES);
|
||||
dev->queuelist = NULL;
|
||||
}
|
||||
dev->queue_count = 0;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
|
||||
drm_dma_takedown( dev );
|
||||
drm_dma_takedown(dev);
|
||||
|
||||
if ( dev->lock.hw_lock ) {
|
||||
dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
|
||||
if (dev->lock.hw_lock) {
|
||||
dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
|
||||
dev->lock.filp = NULL;
|
||||
wake_up_interruptible( &dev->lock.lock_queue );
|
||||
wake_up_interruptible(&dev->lock.lock_queue);
|
||||
}
|
||||
up( &dev->struct_sem );
|
||||
up(&dev->struct_sem);
|
||||
|
||||
DRM_DEBUG("takedown completed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Module initialization. Called via init_module at module load time, or via
|
||||
* linux/init/main.c (this is not currently supported).
|
||||
|
@ -246,26 +246,28 @@ int drm_takedown( drm_device_t *dev )
|
|||
* Initializes an array of drm_device structures, and attempts to
|
||||
* initialize all available devices, using consecutive minors, registering the
|
||||
* stubs and initializing the AGP device.
|
||||
*
|
||||
*
|
||||
* Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
|
||||
* after the initialization for driver customization.
|
||||
*/
|
||||
int drm_init( struct drm_driver *driver )
|
||||
int drm_init(struct drm_driver *driver)
|
||||
{
|
||||
struct pci_dev *pdev = NULL;
|
||||
struct pci_device_id *pid;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG( "\n" );
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
drm_mem_init();
|
||||
|
||||
for (i=0; driver->pci_driver.id_table[i].vendor != 0; i++) {
|
||||
for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
|
||||
pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
|
||||
|
||||
pdev=NULL;
|
||||
/* pass back in pdev to account for multiple identical cards */
|
||||
while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) {
|
||||
|
||||
pdev = NULL;
|
||||
/* pass back in pdev to account for multiple identical cards */
|
||||
while ((pdev =
|
||||
pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
|
||||
pid->subdevice, pdev)) != NULL) {
|
||||
/* stealth mode requires a manual probe */
|
||||
pci_dev_get(pdev);
|
||||
drm_get_dev(pdev, pid, driver);
|
||||
|
@ -273,62 +275,63 @@ int drm_init( struct drm_driver *driver )
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_init);
|
||||
|
||||
/**
|
||||
* Called via cleanup_module() at module unload time.
|
||||
*
|
||||
* Cleans up all DRM device, calling takedown().
|
||||
*
|
||||
*
|
||||
* \sa drm_init
|
||||
*/
|
||||
static void drm_cleanup( drm_device_t *dev )
|
||||
static void drm_cleanup(drm_device_t * dev)
|
||||
{
|
||||
DRM_DEBUG( "\n" );
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!dev) {
|
||||
DRM_ERROR("cleanup called no dev\n");
|
||||
return;
|
||||
}
|
||||
|
||||
drm_takedown( dev );
|
||||
drm_takedown(dev);
|
||||
|
||||
if (dev->maplist) {
|
||||
drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
|
||||
dev->maplist = NULL;
|
||||
}
|
||||
|
||||
drm_ctxbitmap_cleanup( dev );
|
||||
|
||||
drm_ctxbitmap_cleanup(dev);
|
||||
|
||||
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
|
||||
dev->agp && dev->agp->agp_mtrr >= 0) {
|
||||
int retval;
|
||||
retval = mtrr_del( dev->agp->agp_mtrr,
|
||||
dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size*1024*1024 );
|
||||
DRM_DEBUG( "mtrr_del=%d\n", retval );
|
||||
retval = mtrr_del(dev->agp->agp_mtrr,
|
||||
dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size * 1024 * 1024);
|
||||
DRM_DEBUG("mtrr_del=%d\n", retval);
|
||||
}
|
||||
|
||||
if (drm_core_has_AGP(dev) && dev->agp ) {
|
||||
drm_free( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
|
||||
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
|
||||
dev->agp = NULL;
|
||||
}
|
||||
|
||||
if (dev->driver->postcleanup)
|
||||
dev->driver->postcleanup(dev);
|
||||
|
||||
|
||||
drm_put_head(&dev->primary);
|
||||
if ( drm_put_dev(dev) )
|
||||
DRM_ERROR( "Cannot unload module\n" );
|
||||
if (drm_put_dev(dev))
|
||||
DRM_ERROR("Cannot unload module\n");
|
||||
}
|
||||
|
||||
void drm_exit (struct drm_driver *driver)
|
||||
void drm_exit(struct drm_driver *driver)
|
||||
{
|
||||
int i;
|
||||
drm_device_t *dev = NULL;
|
||||
drm_head_t *head;
|
||||
|
||||
DRM_DEBUG( "\n" );
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
for (i = 0; i < drm_cards_limit; i++) {
|
||||
head = drm_heads[i];
|
||||
|
@ -336,9 +339,9 @@ void drm_exit (struct drm_driver *driver)
|
|||
continue;
|
||||
if (!head->dev)
|
||||
continue;
|
||||
if (head->dev->driver!=driver)
|
||||
if (head->dev->driver != driver)
|
||||
continue;
|
||||
dev=head->dev;
|
||||
dev = head->dev;
|
||||
}
|
||||
if (dev) {
|
||||
/* release the pci driver */
|
||||
|
@ -346,32 +349,35 @@ void drm_exit (struct drm_driver *driver)
|
|||
pci_dev_put(dev->pdev);
|
||||
drm_cleanup(dev);
|
||||
}
|
||||
DRM_INFO( "Module unloaded\n" );
|
||||
DRM_INFO("Module unloaded\n");
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_exit);
|
||||
|
||||
/** File operations structure */
|
||||
static struct file_operations drm_stub_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_stub_open
|
||||
.open = drm_stub_open
|
||||
};
|
||||
|
||||
static int __init drm_core_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
|
||||
drm_cards_limit = (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
|
||||
drm_heads = drm_calloc(drm_cards_limit,
|
||||
sizeof(*drm_heads), DRM_MEM_STUB);
|
||||
if(!drm_heads)
|
||||
|
||||
drm_cards_limit =
|
||||
(drm_cards_limit <
|
||||
DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
|
||||
drm_heads =
|
||||
drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB);
|
||||
if (!drm_heads)
|
||||
goto err_p1;
|
||||
|
||||
|
||||
if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
|
||||
goto err_p1;
|
||||
|
||||
|
||||
drm_class = drm_sysfs_create(THIS_MODULE, "drm");
|
||||
if (IS_ERR(drm_class)) {
|
||||
printk (KERN_ERR "DRM: Error creating drm class.\n");
|
||||
printk(KERN_ERR "DRM: Error creating drm class.\n");
|
||||
ret = PTR_ERR(drm_class);
|
||||
goto err_p2;
|
||||
}
|
||||
|
@ -382,35 +388,31 @@ static int __init drm_core_init(void)
|
|||
ret = -1;
|
||||
goto err_p3;
|
||||
}
|
||||
|
||||
DRM_INFO( "Initialized %s %d.%d.%d %s\n",
|
||||
CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL,
|
||||
CORE_DATE);
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s\n",
|
||||
CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
|
||||
return 0;
|
||||
err_p3:
|
||||
err_p3:
|
||||
drm_sysfs_destroy(drm_class);
|
||||
err_p2:
|
||||
err_p2:
|
||||
unregister_chrdev(DRM_MAJOR, "drm");
|
||||
drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
|
||||
err_p1:
|
||||
err_p1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit drm_core_exit (void)
|
||||
static void __exit drm_core_exit(void)
|
||||
{
|
||||
remove_proc_entry("dri", NULL);
|
||||
drm_sysfs_destroy(drm_class);
|
||||
|
||||
unregister_chrdev(DRM_MAJOR, "drm");
|
||||
|
||||
drm_free(drm_heads, sizeof(*drm_heads) *
|
||||
drm_cards_limit, DRM_MEM_STUB);
|
||||
drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
|
||||
}
|
||||
|
||||
|
||||
module_init( drm_core_init );
|
||||
module_exit( drm_core_exit );
|
||||
|
||||
module_init(drm_core_init);
|
||||
module_exit(drm_core_exit);
|
||||
|
||||
/**
|
||||
* Get version information
|
||||
|
@ -423,8 +425,8 @@ module_exit( drm_core_exit );
|
|||
*
|
||||
* Fills in the version information in \p arg.
|
||||
*/
|
||||
static int drm_version( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
static int drm_version(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
@ -432,21 +434,19 @@ static int drm_version( struct inode *inode, struct file *filp,
|
|||
drm_version_t version;
|
||||
int ret;
|
||||
|
||||
if ( copy_from_user( &version, argp, sizeof(version) ) )
|
||||
if (copy_from_user(&version, argp, sizeof(version)))
|
||||
return -EFAULT;
|
||||
|
||||
/* version is a required function to return the personality module version */
|
||||
if ((ret = dev->driver->version(&version)))
|
||||
return ret;
|
||||
|
||||
if ( copy_to_user( argp, &version, sizeof(version) ) )
|
||||
|
||||
if (copy_to_user(argp, &version, sizeof(version)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Called whenever a process performs an ioctl on /dev/drm.
|
||||
*
|
||||
* \param inode device inode.
|
||||
|
@ -458,8 +458,8 @@ static int drm_version( struct inode *inode, struct file *filp,
|
|||
* Looks up the ioctl function in the ::ioctls table, checking for root
|
||||
* previleges if so required, and dispatches to the respective function.
|
||||
*/
|
||||
int drm_ioctl( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
@ -468,40 +468,43 @@ int drm_ioctl( struct inode *inode, struct file *filp,
|
|||
unsigned int nr = DRM_IOCTL_NR(cmd);
|
||||
int retcode = -EINVAL;
|
||||
|
||||
atomic_inc( &dev->ioctl_count );
|
||||
atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
|
||||
atomic_inc(&dev->ioctl_count);
|
||||
atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
|
||||
++priv->ioctl_count;
|
||||
|
||||
DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
|
||||
current->pid, cmd, nr, (long)old_encode_dev(priv->head->device),
|
||||
priv->authenticated );
|
||||
|
||||
DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
|
||||
current->pid, cmd, nr,
|
||||
(long)old_encode_dev(priv->head->device),
|
||||
priv->authenticated);
|
||||
|
||||
if (nr < DRIVER_IOCTL_COUNT)
|
||||
ioctl = &drm_ioctls[nr];
|
||||
else if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
|
||||
else if ((nr >= DRM_COMMAND_BASE)
|
||||
&& (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
|
||||
ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
|
||||
else
|
||||
goto err_i1;
|
||||
|
||||
|
||||
func = ioctl->func;
|
||||
/* is there a local override? */
|
||||
if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
|
||||
func = dev->driver->dma_ioctl;
|
||||
|
||||
if ( !func ) {
|
||||
DRM_DEBUG( "no function\n" );
|
||||
|
||||
if (!func) {
|
||||
DRM_DEBUG("no function\n");
|
||||
retcode = -EINVAL;
|
||||
} else if ( ( ioctl->root_only && !capable( CAP_SYS_ADMIN ) )||
|
||||
( ioctl->auth_needed && !priv->authenticated ) ) {
|
||||
} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) ||
|
||||
(ioctl->auth_needed && !priv->authenticated)) {
|
||||
retcode = -EACCES;
|
||||
} else {
|
||||
retcode = func( inode, filp, cmd, arg );
|
||||
retcode = func(inode, filp, cmd, arg);
|
||||
}
|
||||
|
||||
err_i1:
|
||||
atomic_dec( &dev->ioctl_count );
|
||||
if (retcode) DRM_DEBUG( "ret = %x\n", retcode);
|
||||
|
||||
err_i1:
|
||||
atomic_dec(&dev->ioctl_count);
|
||||
if (retcode)
|
||||
DRM_DEBUG("ret = %x\n", retcode);
|
||||
return retcode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ioctl);
|
||||
|
||||
EXPORT_SYMBOL(drm_ioctl);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* \file drm_fops.h
|
||||
* \file drm_fops.c
|
||||
* File operations for DRM
|
||||
*
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* \author Daryll Strauss <daryll@valinux.com>
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
|
@ -37,49 +37,48 @@
|
|||
#include "drmP.h"
|
||||
#include <linux/poll.h>
|
||||
|
||||
static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev);
|
||||
static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
drm_device_t * dev);
|
||||
|
||||
static int drm_setup( drm_device_t *dev )
|
||||
static int drm_setup(drm_device_t * dev)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (dev->driver->presetup)
|
||||
{
|
||||
ret=dev->driver->presetup(dev);
|
||||
if (ret!=0)
|
||||
if (dev->driver->presetup) {
|
||||
ret = dev->driver->presetup(dev);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
atomic_set( &dev->ioctl_count, 0 );
|
||||
atomic_set( &dev->vma_count, 0 );
|
||||
atomic_set(&dev->ioctl_count, 0);
|
||||
atomic_set(&dev->vma_count, 0);
|
||||
dev->buf_use = 0;
|
||||
atomic_set( &dev->buf_alloc, 0 );
|
||||
atomic_set(&dev->buf_alloc, 0);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
|
||||
{
|
||||
i = drm_dma_setup( dev );
|
||||
if ( i < 0 )
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
|
||||
i = drm_dma_setup(dev);
|
||||
if (i < 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
|
||||
atomic_set( &dev->counts[i], 0 );
|
||||
for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
|
||||
atomic_set(&dev->counts[i], 0);
|
||||
|
||||
for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
|
||||
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
||||
dev->magiclist[i].head = NULL;
|
||||
dev->magiclist[i].tail = NULL;
|
||||
}
|
||||
|
||||
dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist),
|
||||
DRM_MEM_CTXLIST);
|
||||
if(dev->ctxlist == NULL) return -ENOMEM;
|
||||
dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
|
||||
if (dev->ctxlist == NULL)
|
||||
return -ENOMEM;
|
||||
memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
|
||||
INIT_LIST_HEAD(&dev->ctxlist->head);
|
||||
|
||||
dev->vmalist = NULL;
|
||||
dev->sigdata.lock = dev->lock.hw_lock = NULL;
|
||||
init_waitqueue_head( &dev->lock.lock_queue );
|
||||
init_waitqueue_head(&dev->lock.lock_queue);
|
||||
dev->queue_count = 0;
|
||||
dev->queue_reserved = 0;
|
||||
dev->queue_slots = 0;
|
||||
|
@ -91,24 +90,21 @@ static int drm_setup( drm_device_t *dev )
|
|||
dev->last_context = 0;
|
||||
dev->last_switch = 0;
|
||||
dev->last_checked = 0;
|
||||
init_waitqueue_head( &dev->context_wait );
|
||||
init_waitqueue_head(&dev->context_wait);
|
||||
dev->if_version = 0;
|
||||
|
||||
dev->ctx_start = 0;
|
||||
dev->lck_start = 0;
|
||||
|
||||
dev->buf_rp = dev->buf;
|
||||
dev->buf_wp = dev->buf;
|
||||
dev->buf_end = dev->buf + DRM_BSZ;
|
||||
dev->buf_async = NULL;
|
||||
init_waitqueue_head( &dev->buf_readers );
|
||||
init_waitqueue_head( &dev->buf_writers );
|
||||
init_waitqueue_head(&dev->buf_readers);
|
||||
init_waitqueue_head(&dev->buf_writers);
|
||||
|
||||
DRM_DEBUG( "\n" );
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/*
|
||||
* The kernel's context could be created here, but is now created
|
||||
* in drm_dma_enqueue. This is more resource-efficient for
|
||||
* in drm_dma_enqueue. This is more resource-efficient for
|
||||
* hardware that does not do DMA, but may mean that
|
||||
* drm_select_queue fails between the time the interrupt is
|
||||
* initialized and the time the queues are initialized.
|
||||
|
@ -121,7 +117,7 @@ static int drm_setup( drm_device_t *dev )
|
|||
|
||||
/**
|
||||
* Open file.
|
||||
*
|
||||
*
|
||||
* \param inode device inode
|
||||
* \param filp file pointer.
|
||||
* \return zero on success or a negative number on failure.
|
||||
|
@ -130,7 +126,7 @@ static int drm_setup( drm_device_t *dev )
|
|||
* increments the device open count. If the open count was previous at zero,
|
||||
* i.e., it's the first that the device is open, then calls setup().
|
||||
*/
|
||||
int drm_open( struct inode *inode, struct file *filp )
|
||||
int drm_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
drm_device_t *dev = NULL;
|
||||
int minor = iminor(inode);
|
||||
|
@ -138,26 +134,27 @@ int drm_open( struct inode *inode, struct file *filp )
|
|||
|
||||
if (!((minor >= 0) && (minor < drm_cards_limit)))
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
if (!drm_heads[minor])
|
||||
return -ENODEV;
|
||||
|
||||
if (!(dev = drm_heads[minor]->dev))
|
||||
return -ENODEV;
|
||||
|
||||
retcode = drm_open_helper( inode, filp, dev );
|
||||
if ( !retcode ) {
|
||||
atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
|
||||
spin_lock( &dev->count_lock );
|
||||
if ( !dev->open_count++ ) {
|
||||
spin_unlock( &dev->count_lock );
|
||||
return drm_setup( dev );
|
||||
|
||||
retcode = drm_open_helper(inode, filp, dev);
|
||||
if (!retcode) {
|
||||
atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
|
||||
spin_lock(&dev->count_lock);
|
||||
if (!dev->open_count++) {
|
||||
spin_unlock(&dev->count_lock);
|
||||
return drm_setup(dev);
|
||||
}
|
||||
spin_unlock( &dev->count_lock );
|
||||
spin_unlock(&dev->count_lock);
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_open);
|
||||
|
||||
/**
|
||||
|
@ -172,7 +169,7 @@ EXPORT_SYMBOL(drm_open);
|
|||
* data from its list and free it. Decreases the open count and if it reaches
|
||||
* zero calls takedown().
|
||||
*/
|
||||
int drm_release( struct inode *inode, struct file *filp )
|
||||
int drm_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev;
|
||||
|
@ -181,7 +178,7 @@ int drm_release( struct inode *inode, struct file *filp )
|
|||
lock_kernel();
|
||||
dev = priv->head->dev;
|
||||
|
||||
DRM_DEBUG( "open_count = %d\n", dev->open_count );
|
||||
DRM_DEBUG("open_count = %d\n", dev->open_count);
|
||||
|
||||
if (dev->driver->prerelease)
|
||||
dev->driver->prerelease(dev, filp);
|
||||
|
@ -190,194 +187,199 @@ int drm_release( struct inode *inode, struct file *filp )
|
|||
* Begin inline drm_release
|
||||
*/
|
||||
|
||||
DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
|
||||
current->pid, (long)old_encode_dev(priv->head->device), dev->open_count );
|
||||
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
|
||||
current->pid, (long)old_encode_dev(priv->head->device),
|
||||
dev->open_count);
|
||||
|
||||
if (priv->lock_count && dev->lock.hw_lock &&
|
||||
_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
|
||||
dev->lock.filp == filp) {
|
||||
DRM_DEBUG("File %p released, freeing lock for context %d\n",
|
||||
filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
|
||||
|
||||
if ( priv->lock_count && dev->lock.hw_lock &&
|
||||
_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
|
||||
dev->lock.filp == filp ) {
|
||||
DRM_DEBUG( "File %p released, freeing lock for context %d\n",
|
||||
filp,
|
||||
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
|
||||
|
||||
if (dev->driver->release)
|
||||
dev->driver->release(dev, filp);
|
||||
|
||||
drm_lock_free( dev, &dev->lock.hw_lock->lock,
|
||||
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
|
||||
drm_lock_free(dev, &dev->lock.hw_lock->lock,
|
||||
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
|
||||
|
||||
/* FIXME: may require heavy-handed reset of
|
||||
hardware at this point, possibly
|
||||
processed via a callback to the X
|
||||
server. */
|
||||
}
|
||||
else if ( dev->driver->release && priv->lock_count && dev->lock.hw_lock ) {
|
||||
/* FIXME: may require heavy-handed reset of
|
||||
hardware at this point, possibly
|
||||
processed via a callback to the X
|
||||
server. */
|
||||
} else if (dev->driver->release && priv->lock_count
|
||||
&& dev->lock.hw_lock) {
|
||||
/* The lock is required to reclaim buffers */
|
||||
DECLARE_WAITQUEUE( entry, current );
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
|
||||
add_wait_queue( &dev->lock.lock_queue, &entry );
|
||||
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
for (;;) {
|
||||
__set_current_state(TASK_INTERRUPTIBLE);
|
||||
if ( !dev->lock.hw_lock ) {
|
||||
if (!dev->lock.hw_lock) {
|
||||
/* Device has been unregistered */
|
||||
retcode = -EINTR;
|
||||
break;
|
||||
}
|
||||
if ( drm_lock_take( &dev->lock.hw_lock->lock,
|
||||
DRM_KERNEL_CONTEXT ) ) {
|
||||
dev->lock.filp = filp;
|
||||
if (drm_lock_take(&dev->lock.hw_lock->lock,
|
||||
DRM_KERNEL_CONTEXT)) {
|
||||
dev->lock.filp = filp;
|
||||
dev->lock.lock_time = jiffies;
|
||||
atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
|
||||
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
|
||||
break; /* Got lock */
|
||||
}
|
||||
/* Contention */
|
||||
/* Contention */
|
||||
schedule();
|
||||
if ( signal_pending( current ) ) {
|
||||
if (signal_pending(current)) {
|
||||
retcode = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue( &dev->lock.lock_queue, &entry );
|
||||
if( !retcode ) {
|
||||
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
if (!retcode) {
|
||||
if (dev->driver->release)
|
||||
dev->driver->release(dev, filp);
|
||||
drm_lock_free( dev, &dev->lock.hw_lock->lock,
|
||||
DRM_KERNEL_CONTEXT );
|
||||
drm_lock_free(dev, &dev->lock.hw_lock->lock,
|
||||
DRM_KERNEL_CONTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !dev->driver->release)
|
||||
{
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)
|
||||
&& !dev->driver->release) {
|
||||
dev->driver->reclaim_buffers(dev, filp);
|
||||
}
|
||||
|
||||
drm_fasync( -1, filp, 0 );
|
||||
drm_fasync(-1, filp, 0);
|
||||
|
||||
down( &dev->ctxlist_sem );
|
||||
if ( dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
|
||||
down(&dev->ctxlist_sem);
|
||||
if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
|
||||
drm_ctx_list_t *pos, *n;
|
||||
|
||||
list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
|
||||
if ( pos->tag == priv &&
|
||||
pos->handle != DRM_KERNEL_CONTEXT ) {
|
||||
list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
|
||||
if (pos->tag == priv &&
|
||||
pos->handle != DRM_KERNEL_CONTEXT) {
|
||||
if (dev->driver->context_dtor)
|
||||
dev->driver->context_dtor(dev, pos->handle);
|
||||
dev->driver->context_dtor(dev,
|
||||
pos->handle);
|
||||
|
||||
drm_ctxbitmap_free( dev, pos->handle );
|
||||
drm_ctxbitmap_free(dev, pos->handle);
|
||||
|
||||
list_del( &pos->head );
|
||||
drm_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
|
||||
list_del(&pos->head);
|
||||
drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
|
||||
--dev->ctx_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
up( &dev->ctxlist_sem );
|
||||
up(&dev->ctxlist_sem);
|
||||
|
||||
down( &dev->struct_sem );
|
||||
if ( priv->remove_auth_on_close == 1 ) {
|
||||
down(&dev->struct_sem);
|
||||
if (priv->remove_auth_on_close == 1) {
|
||||
drm_file_t *temp = dev->file_first;
|
||||
while ( temp ) {
|
||||
while (temp) {
|
||||
temp->authenticated = 0;
|
||||
temp = temp->next;
|
||||
}
|
||||
}
|
||||
if ( priv->prev ) {
|
||||
if (priv->prev) {
|
||||
priv->prev->next = priv->next;
|
||||
} else {
|
||||
dev->file_first = priv->next;
|
||||
dev->file_first = priv->next;
|
||||
}
|
||||
if ( priv->next ) {
|
||||
if (priv->next) {
|
||||
priv->next->prev = priv->prev;
|
||||
} else {
|
||||
dev->file_last = priv->prev;
|
||||
dev->file_last = priv->prev;
|
||||
}
|
||||
up( &dev->struct_sem );
|
||||
|
||||
up(&dev->struct_sem);
|
||||
|
||||
if (dev->driver->free_filp_priv)
|
||||
dev->driver->free_filp_priv(dev, priv);
|
||||
|
||||
drm_free( priv, sizeof(*priv), DRM_MEM_FILES );
|
||||
drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
|
||||
|
||||
/* ========================================================
|
||||
* End inline drm_release
|
||||
*/
|
||||
|
||||
atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
|
||||
spin_lock( &dev->count_lock );
|
||||
if ( !--dev->open_count ) {
|
||||
if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
|
||||
DRM_ERROR( "Device busy: %d %d\n",
|
||||
atomic_read( &dev->ioctl_count ),
|
||||
dev->blocked );
|
||||
spin_unlock( &dev->count_lock );
|
||||
atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
|
||||
spin_lock(&dev->count_lock);
|
||||
if (!--dev->open_count) {
|
||||
if (atomic_read(&dev->ioctl_count) || dev->blocked) {
|
||||
DRM_ERROR("Device busy: %d %d\n",
|
||||
atomic_read(&dev->ioctl_count), dev->blocked);
|
||||
spin_unlock(&dev->count_lock);
|
||||
unlock_kernel();
|
||||
return -EBUSY;
|
||||
}
|
||||
spin_unlock( &dev->count_lock );
|
||||
spin_unlock(&dev->count_lock);
|
||||
unlock_kernel();
|
||||
return drm_takedown( dev );
|
||||
return drm_takedown(dev);
|
||||
}
|
||||
spin_unlock( &dev->count_lock );
|
||||
spin_unlock(&dev->count_lock);
|
||||
|
||||
unlock_kernel();
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_release);
|
||||
|
||||
/**
|
||||
* Called whenever a process opens /dev/drm.
|
||||
* Called whenever a process opens /dev/drm.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param dev device.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
*
|
||||
* Creates and initializes a drm_file structure for the file private data in \p
|
||||
* filp and add it into the double linked list in \p dev.
|
||||
*/
|
||||
static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
|
||||
static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
drm_device_t * dev)
|
||||
{
|
||||
int minor = iminor(inode);
|
||||
drm_file_t *priv;
|
||||
int minor = iminor(inode);
|
||||
drm_file_t *priv;
|
||||
int ret;
|
||||
|
||||
if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
|
||||
if (!drm_cpu_valid()) return -EINVAL;
|
||||
if (filp->f_flags & O_EXCL)
|
||||
return -EBUSY; /* No exclusive opens */
|
||||
if (!drm_cpu_valid())
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
|
||||
|
||||
priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
|
||||
if(!priv) return -ENOMEM;
|
||||
priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
filp->private_data = priv;
|
||||
priv->uid = current->euid;
|
||||
priv->pid = current->pid;
|
||||
priv->minor = minor;
|
||||
priv->head = drm_heads[minor];
|
||||
priv->ioctl_count = 0;
|
||||
filp->private_data = priv;
|
||||
priv->uid = current->euid;
|
||||
priv->pid = current->pid;
|
||||
priv->minor = minor;
|
||||
priv->head = drm_heads[minor];
|
||||
priv->ioctl_count = 0;
|
||||
priv->authenticated = capable(CAP_SYS_ADMIN);
|
||||
priv->lock_count = 0;
|
||||
priv->lock_count = 0;
|
||||
|
||||
if (dev->driver->open_helper) {
|
||||
ret=dev->driver->open_helper(dev, priv);
|
||||
ret = dev->driver->open_helper(dev, priv);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
down(&dev->struct_sem);
|
||||
if (!dev->file_last) {
|
||||
priv->next = NULL;
|
||||
priv->prev = NULL;
|
||||
priv->next = NULL;
|
||||
priv->prev = NULL;
|
||||
dev->file_first = priv;
|
||||
dev->file_last = priv;
|
||||
dev->file_last = priv;
|
||||
} else {
|
||||
priv->next = NULL;
|
||||
priv->prev = dev->file_last;
|
||||
priv->next = NULL;
|
||||
priv->prev = dev->file_last;
|
||||
dev->file_last->next = priv;
|
||||
dev->file_last = priv;
|
||||
dev->file_last = priv;
|
||||
}
|
||||
up(&dev->struct_sem);
|
||||
|
||||
|
@ -394,42 +396,48 @@ static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t
|
|||
}
|
||||
if (!dev->hose) {
|
||||
struct pci_bus *b = pci_bus_b(pci_root_buses.next);
|
||||
if (b) dev->hose = b->sysdata;
|
||||
if (b)
|
||||
dev->hose = b->sysdata;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
out_free:
|
||||
out_free:
|
||||
drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
|
||||
filp->private_data=NULL;
|
||||
filp->private_data = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** No-op. */
|
||||
int drm_flush(struct file *filp)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
||||
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
|
||||
current->pid, (long)old_encode_dev(priv->head->device), dev->open_count);
|
||||
current->pid, (long)old_encode_dev(priv->head->device),
|
||||
dev->open_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_flush);
|
||||
|
||||
/** No-op. */
|
||||
int drm_fasync(int fd, struct file *filp, int on)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
int retcode;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
int retcode;
|
||||
|
||||
DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)old_encode_dev(priv->head->device));
|
||||
DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
|
||||
(long)old_encode_dev(priv->head->device));
|
||||
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
|
||||
if (retcode < 0) return retcode;
|
||||
if (retcode < 0)
|
||||
return retcode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_fasync);
|
||||
|
||||
/** No-op. */
|
||||
|
@ -437,5 +445,5 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_poll);
|
||||
|
||||
EXPORT_SYMBOL(drm_poll);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_init.h
|
||||
* \file drm_init.c
|
||||
* Setup/Cleanup for DRM
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -43,10 +43,11 @@
|
|||
int drm_cpu_valid(void)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
|
||||
if (boot_cpu_data.x86 == 3)
|
||||
return 0; /* No cmpxchg on a 386 */
|
||||
#endif
|
||||
#if defined(__sparc__) && !defined(__sparc_v9__)
|
||||
return 0; /* No cmpxchg before v9 sparc. */
|
||||
return 0; /* No cmpxchg before v9 sparc. */
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -68,15 +68,15 @@
|
|||
#define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
|
||||
|
||||
typedef struct drm_version_32 {
|
||||
int version_major; /**< Major version */
|
||||
int version_minor; /**< Minor version */
|
||||
int version_patchlevel;/**< Patch level */
|
||||
u32 name_len; /**< Length of name buffer */
|
||||
u32 name; /**< Name of driver */
|
||||
u32 date_len; /**< Length of date buffer */
|
||||
u32 date; /**< User-space buffer to hold date */
|
||||
u32 desc_len; /**< Length of desc buffer */
|
||||
u32 desc; /**< User-space buffer to hold desc */
|
||||
int version_major; /**< Major version */
|
||||
int version_minor; /**< Minor version */
|
||||
int version_patchlevel; /**< Patch level */
|
||||
u32 name_len; /**< Length of name buffer */
|
||||
u32 name; /**< Name of driver */
|
||||
u32 date_len; /**< Length of date buffer */
|
||||
u32 date; /**< User-space buffer to hold date */
|
||||
u32 desc_len; /**< Length of desc buffer */
|
||||
u32 desc; /**< User-space buffer to hold desc */
|
||||
} drm_version32_t;
|
||||
|
||||
static int compat_drm_version(struct file *file, unsigned int cmd,
|
||||
|
@ -86,7 +86,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
|
|||
drm_version_t __user *version;
|
||||
int err;
|
||||
|
||||
if (copy_from_user(&v32, (void __user *) arg, sizeof(v32)))
|
||||
if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
|
||||
return -EFAULT;
|
||||
|
||||
version = compat_alloc_user_space(sizeof(*version));
|
||||
|
@ -104,7 +104,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_VERSION, (unsigned long) version);
|
||||
DRM_IOCTL_VERSION, (unsigned long)version);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -116,7 +116,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
|
|||
|| __get_user(v32.desc_len, &version->desc_len))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_to_user((void __user *) arg, &v32, sizeof(v32)))
|
||||
if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -133,25 +133,25 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
|
|||
drm_unique_t __user *u;
|
||||
int err;
|
||||
|
||||
if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
|
||||
if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
|
||||
return -EFAULT;
|
||||
|
||||
u = compat_alloc_user_space(sizeof(*u));
|
||||
if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
|
||||
return -EFAULT;
|
||||
if (__put_user(uq32.unique_len, &u->unique_len)
|
||||
|| __put_user((void __user *)(unsigned long) uq32.unique,
|
||||
|| __put_user((void __user *)(unsigned long)uq32.unique,
|
||||
&u->unique))
|
||||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_GET_UNIQUE, (unsigned long) u);
|
||||
DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (__get_user(uq32.unique_len, &u->unique_len))
|
||||
return -EFAULT;
|
||||
if (copy_to_user((void __user *) arg, &uq32, sizeof(uq32)))
|
||||
if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,28 +162,28 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
|
|||
drm_unique32_t uq32;
|
||||
drm_unique_t __user *u;
|
||||
|
||||
if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
|
||||
if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
|
||||
return -EFAULT;
|
||||
|
||||
u = compat_alloc_user_space(sizeof(*u));
|
||||
if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
|
||||
return -EFAULT;
|
||||
if (__put_user(uq32.unique_len, &u->unique_len)
|
||||
|| __put_user((void __user *)(unsigned long) uq32.unique,
|
||||
|| __put_user((void __user *)(unsigned long)uq32.unique,
|
||||
&u->unique))
|
||||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_SET_UNIQUE, (unsigned long) u);
|
||||
DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
|
||||
}
|
||||
|
||||
typedef struct drm_map32 {
|
||||
u32 offset; /**< Requested physical address (0 for SAREA)*/
|
||||
u32 size; /**< Requested physical size (bytes) */
|
||||
drm_map_type_t type; /**< Type of memory to map */
|
||||
u32 offset; /**< Requested physical address (0 for SAREA)*/
|
||||
u32 size; /**< Requested physical size (bytes) */
|
||||
drm_map_type_t type; /**< Type of memory to map */
|
||||
drm_map_flags_t flags; /**< Flags */
|
||||
u32 handle; /**< User-space: "Handle" to pass to mmap() */
|
||||
int mtrr; /**< MTRR slot used */
|
||||
u32 handle; /**< User-space: "Handle" to pass to mmap() */
|
||||
int mtrr; /**< MTRR slot used */
|
||||
} drm_map32_t;
|
||||
|
||||
static int compat_drm_getmap(struct file *file, unsigned int cmd,
|
||||
|
@ -205,7 +205,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_GET_MAP, (unsigned long) map);
|
||||
DRM_IOCTL_GET_MAP, (unsigned long)map);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -217,7 +217,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
|
|||
|| __get_user(m32.mtrr, &map->mtrr))
|
||||
return -EFAULT;
|
||||
|
||||
m32.handle = (unsigned long) handle;
|
||||
m32.handle = (unsigned long)handle;
|
||||
if (copy_to_user(argp, &m32, sizeof(m32)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
@ -246,7 +246,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_ADD_MAP, (unsigned long) map);
|
||||
DRM_IOCTL_ADD_MAP, (unsigned long)map);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -255,8 +255,8 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
|
|||
|| __get_user(handle, &map->handle))
|
||||
return -EFAULT;
|
||||
|
||||
m32.handle = (unsigned long) handle;
|
||||
if (m32.handle != (unsigned long) handle && printk_ratelimit())
|
||||
m32.handle = (unsigned long)handle;
|
||||
if (m32.handle != (unsigned long)handle && printk_ratelimit())
|
||||
printk(KERN_ERR "compat_drm_addmap truncated handle"
|
||||
" %p for type %d offset %x\n",
|
||||
handle, m32.type, m32.offset);
|
||||
|
@ -280,20 +280,20 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
|
|||
map = compat_alloc_user_space(sizeof(*map));
|
||||
if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
|
||||
return -EFAULT;
|
||||
if (__put_user((void *)(unsigned long) handle, &map->handle))
|
||||
if (__put_user((void *)(unsigned long)handle, &map->handle))
|
||||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_RM_MAP, (unsigned long) map);
|
||||
DRM_IOCTL_RM_MAP, (unsigned long)map);
|
||||
}
|
||||
|
||||
typedef struct drm_client32 {
|
||||
int idx; /**< Which client desired? */
|
||||
int auth; /**< Is client authenticated? */
|
||||
u32 pid; /**< Process ID */
|
||||
u32 uid; /**< User ID */
|
||||
u32 magic; /**< Magic */
|
||||
u32 iocs; /**< Ioctl count */
|
||||
int idx; /**< Which client desired? */
|
||||
int auth; /**< Is client authenticated? */
|
||||
u32 pid; /**< Process ID */
|
||||
u32 uid; /**< User ID */
|
||||
u32 magic; /**< Magic */
|
||||
u32 iocs; /**< Ioctl count */
|
||||
} drm_client32_t;
|
||||
|
||||
static int compat_drm_getclient(struct file *file, unsigned int cmd,
|
||||
|
@ -314,7 +314,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_GET_CLIENT, (unsigned long) client);
|
||||
DRM_IOCTL_GET_CLIENT, (unsigned long)client);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -351,7 +351,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_GET_STATS, (unsigned long) stats);
|
||||
DRM_IOCTL_GET_STATS, (unsigned long)stats);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -368,12 +368,12 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
|
|||
}
|
||||
|
||||
typedef struct drm_buf_desc32 {
|
||||
int count; /**< Number of buffers of this size */
|
||||
int size; /**< Size in bytes */
|
||||
int low_mark; /**< Low water mark */
|
||||
int high_mark; /**< High water mark */
|
||||
int flags;
|
||||
u32 agp_start; /**< Start address in the AGP aperture */
|
||||
int count; /**< Number of buffers of this size */
|
||||
int size; /**< Size in bytes */
|
||||
int low_mark; /**< Low water mark */
|
||||
int high_mark; /**< High water mark */
|
||||
int flags;
|
||||
u32 agp_start; /**< Start address in the AGP aperture */
|
||||
} drm_buf_desc32_t;
|
||||
|
||||
static int compat_drm_addbufs(struct file *file, unsigned int cmd,
|
||||
|
@ -395,7 +395,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_ADD_BUFS, (unsigned long) buf);
|
||||
DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -427,12 +427,12 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_MARK_BUFS, (unsigned long) buf);
|
||||
DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
|
||||
}
|
||||
|
||||
typedef struct drm_buf_info32 {
|
||||
int count; /**< Entries in list */
|
||||
u32 list;
|
||||
int count; /**< Entries in list */
|
||||
u32 list;
|
||||
} drm_buf_info32_t;
|
||||
|
||||
static int compat_drm_infobufs(struct file *file, unsigned int cmd,
|
||||
|
@ -451,7 +451,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
count = req32.count;
|
||||
to = (drm_buf_desc32_t __user *)(unsigned long) req32.list;
|
||||
to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
if (count > 0
|
||||
|
@ -469,7 +469,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_INFO_BUFS, (unsigned long) request);
|
||||
DRM_IOCTL_INFO_BUFS, (unsigned long)request);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -488,16 +488,16 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
|
|||
}
|
||||
|
||||
typedef struct drm_buf_pub32 {
|
||||
int idx; /**< Index into the master buffer list */
|
||||
int total; /**< Buffer size */
|
||||
int used; /**< Amount of buffer in use (for DMA) */
|
||||
u32 address; /**< Address of buffer */
|
||||
int idx; /**< Index into the master buffer list */
|
||||
int total; /**< Buffer size */
|
||||
int used; /**< Amount of buffer in use (for DMA) */
|
||||
u32 address; /**< Address of buffer */
|
||||
} drm_buf_pub32_t;
|
||||
|
||||
typedef struct drm_buf_map32 {
|
||||
int count; /**< Length of the buffer list */
|
||||
u32 virtual; /**< Mmap'd area in user-virtual */
|
||||
u32 list; /**< Buffer information */
|
||||
int count; /**< Length of the buffer list */
|
||||
u32 virtual; /**< Mmap'd area in user-virtual */
|
||||
u32 list; /**< Buffer information */
|
||||
} drm_buf_map32_t;
|
||||
|
||||
static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
|
||||
|
@ -531,7 +531,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_MAP_BUFS, (unsigned long) request);
|
||||
DRM_IOCTL_MAP_BUFS, (unsigned long)request);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -542,21 +542,21 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
|
|||
if (__copy_in_user(&list32[i], &list[i],
|
||||
offsetof(drm_buf_pub_t, address))
|
||||
|| __get_user(addr, &list[i].address)
|
||||
|| __put_user((unsigned long) addr,
|
||||
|| __put_user((unsigned long)addr,
|
||||
&list32[i].address))
|
||||
return -EFAULT;
|
||||
|
||||
if (__put_user(actual, &argp->count)
|
||||
|| __get_user(addr, &request->virtual)
|
||||
|| __put_user((unsigned long) addr, &argp->virtual))
|
||||
|| __put_user((unsigned long)addr, &argp->virtual))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct drm_buf_free32 {
|
||||
int count;
|
||||
u32 list;
|
||||
int count;
|
||||
u32 list;
|
||||
} drm_buf_free32_t;
|
||||
|
||||
static int compat_drm_freebufs(struct file *file, unsigned int cmd,
|
||||
|
@ -573,17 +573,17 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
|
|||
if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
|
||||
return -EFAULT;
|
||||
if (__put_user(req32.count, &request->count)
|
||||
|| __put_user((int __user *)(unsigned long) req32.list,
|
||||
|| __put_user((int __user *)(unsigned long)req32.list,
|
||||
&request->list))
|
||||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_FREE_BUFS, (unsigned long) request);
|
||||
DRM_IOCTL_FREE_BUFS, (unsigned long)request);
|
||||
}
|
||||
|
||||
typedef struct drm_ctx_priv_map32 {
|
||||
unsigned int ctx_id; /**< Context requesting private mapping */
|
||||
u32 handle; /**< Handle of map */
|
||||
unsigned int ctx_id; /**< Context requesting private mapping */
|
||||
u32 handle; /**< Handle of map */
|
||||
} drm_ctx_priv_map32_t;
|
||||
|
||||
static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
|
||||
|
@ -600,12 +600,12 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
|
|||
if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
|
||||
return -EFAULT;
|
||||
if (__put_user(req32.ctx_id, &request->ctx_id)
|
||||
|| __put_user((void *)(unsigned long) req32.handle,
|
||||
|| __put_user((void *)(unsigned long)req32.handle,
|
||||
&request->handle))
|
||||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_SET_SAREA_CTX, (unsigned long) request);
|
||||
DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
|
||||
}
|
||||
|
||||
static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
|
||||
|
@ -628,20 +628,20 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_GET_SAREA_CTX, (unsigned long) request);
|
||||
DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (__get_user(handle, &request->handle)
|
||||
|| __put_user((unsigned long) handle, &argp->handle))
|
||||
|| __put_user((unsigned long)handle, &argp->handle))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct drm_ctx_res32 {
|
||||
int count;
|
||||
u32 contexts;
|
||||
int count;
|
||||
u32 contexts;
|
||||
} drm_ctx_res32_t;
|
||||
|
||||
static int compat_drm_resctx(struct file *file, unsigned int cmd,
|
||||
|
@ -659,12 +659,12 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
|
|||
if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
|
||||
return -EFAULT;
|
||||
if (__put_user(res32.count, &res->count)
|
||||
|| __put_user((drm_ctx_t __user *)(unsigned long) res32.contexts,
|
||||
|| __put_user((drm_ctx_t __user *) (unsigned long)res32.contexts,
|
||||
&res->contexts))
|
||||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_RES_CTX, (unsigned long) res);
|
||||
DRM_IOCTL_RES_CTX, (unsigned long)res);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -676,23 +676,23 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
|
|||
}
|
||||
|
||||
typedef struct drm_dma32 {
|
||||
int context; /**< Context handle */
|
||||
int send_count; /**< Number of buffers to send */
|
||||
u32 send_indices; /**< List of handles to buffers */
|
||||
u32 send_sizes; /**< Lengths of data to send */
|
||||
int context; /**< Context handle */
|
||||
int send_count; /**< Number of buffers to send */
|
||||
u32 send_indices; /**< List of handles to buffers */
|
||||
u32 send_sizes; /**< Lengths of data to send */
|
||||
drm_dma_flags_t flags; /**< Flags */
|
||||
int request_count; /**< Number of buffers requested */
|
||||
int request_size; /**< Desired size for buffers */
|
||||
u32 request_indices; /**< Buffer information */
|
||||
u32 request_sizes;
|
||||
int granted_count; /**< Number of buffers granted */
|
||||
int request_count; /**< Number of buffers requested */
|
||||
int request_size; /**< Desired size for buffers */
|
||||
u32 request_indices; /**< Buffer information */
|
||||
u32 request_sizes;
|
||||
int granted_count; /**< Number of buffers granted */
|
||||
} drm_dma32_t;
|
||||
|
||||
static int compat_drm_dma(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_dma32_t d32;
|
||||
drm_dma32_t __user *argp = (void __user *) arg;
|
||||
drm_dma32_t __user *argp = (void __user *)arg;
|
||||
drm_dma_t __user *d;
|
||||
int err;
|
||||
|
||||
|
@ -705,20 +705,20 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
|
|||
|
||||
if (__put_user(d32.context, &d->context)
|
||||
|| __put_user(d32.send_count, &d->send_count)
|
||||
|| __put_user((int __user *)(unsigned long) d32.send_indices,
|
||||
|| __put_user((int __user *)(unsigned long)d32.send_indices,
|
||||
&d->send_indices)
|
||||
|| __put_user((int __user *)(unsigned long) d32.send_sizes,
|
||||
|| __put_user((int __user *)(unsigned long)d32.send_sizes,
|
||||
&d->send_sizes)
|
||||
|| __put_user(d32.flags, &d->flags)
|
||||
|| __put_user(d32.request_count, &d->request_count)
|
||||
|| __put_user((int __user *)(unsigned long) d32.request_indices,
|
||||
|| __put_user((int __user *)(unsigned long)d32.request_indices,
|
||||
&d->request_indices)
|
||||
|| __put_user((int __user *)(unsigned long) d32.request_sizes,
|
||||
|| __put_user((int __user *)(unsigned long)d32.request_sizes,
|
||||
&d->request_sizes))
|
||||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_DMA, (unsigned long) d);
|
||||
DRM_IOCTL_DMA, (unsigned long)d);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -751,19 +751,19 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_AGP_ENABLE, (unsigned long) mode);
|
||||
DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
|
||||
}
|
||||
|
||||
typedef struct drm_agp_info32 {
|
||||
int agp_version_major;
|
||||
int agp_version_minor;
|
||||
u32 mode;
|
||||
u32 aperture_base; /* physical address */
|
||||
u32 aperture_size; /* bytes */
|
||||
u32 memory_allowed; /* bytes */
|
||||
u32 memory_used;
|
||||
int agp_version_major;
|
||||
int agp_version_minor;
|
||||
u32 mode;
|
||||
u32 aperture_base; /* physical address */
|
||||
u32 aperture_size; /* bytes */
|
||||
u32 memory_allowed; /* bytes */
|
||||
u32 memory_used;
|
||||
|
||||
/* PCI information */
|
||||
/* PCI information */
|
||||
unsigned short id_vendor;
|
||||
unsigned short id_device;
|
||||
} drm_agp_info32_t;
|
||||
|
@ -781,7 +781,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_AGP_INFO, (unsigned long) info);
|
||||
DRM_IOCTL_AGP_INFO, (unsigned long)info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -806,7 +806,7 @@ typedef struct drm_agp_buffer32 {
|
|||
u32 size; /**< In bytes -- will round to page boundary */
|
||||
u32 handle; /**< Used for binding / unbinding */
|
||||
u32 type; /**< Type of memory to allocate */
|
||||
u32 physical; /**< Physical used by i810 */
|
||||
u32 physical; /**< Physical used by i810 */
|
||||
} drm_agp_buffer32_t;
|
||||
|
||||
static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
|
||||
|
@ -827,7 +827,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_AGP_ALLOC, (unsigned long) request);
|
||||
DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -835,7 +835,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
|
|||
|| __get_user(req32.physical, &request->physical)
|
||||
|| copy_to_user(argp, &req32, sizeof(req32))) {
|
||||
drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_AGP_FREE, (unsigned long) request);
|
||||
DRM_IOCTL_AGP_FREE, (unsigned long)request);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -856,7 +856,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_AGP_FREE, (unsigned long) request);
|
||||
DRM_IOCTL_AGP_FREE, (unsigned long)request);
|
||||
}
|
||||
|
||||
typedef struct drm_agp_binding32 {
|
||||
|
@ -881,7 +881,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_AGP_BIND, (unsigned long) request);
|
||||
DRM_IOCTL_AGP_BIND, (unsigned long)request);
|
||||
}
|
||||
|
||||
static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
|
||||
|
@ -898,9 +898,9 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_AGP_UNBIND, (unsigned long) request);
|
||||
DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
|
||||
}
|
||||
#endif /* __OS_HAS_AGP */
|
||||
#endif /* __OS_HAS_AGP */
|
||||
|
||||
typedef struct drm_scatter_gather32 {
|
||||
u32 size; /**< In bytes -- will round to page boundary */
|
||||
|
@ -923,7 +923,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_SG_ALLOC, (unsigned long) request);
|
||||
DRM_IOCTL_SG_ALLOC, (unsigned long)request);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -950,7 +950,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_SG_FREE, (unsigned long) request);
|
||||
DRM_IOCTL_SG_FREE, (unsigned long)request);
|
||||
}
|
||||
|
||||
struct drm_wait_vblank_request32 {
|
||||
|
@ -990,7 +990,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
err = drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_WAIT_VBLANK, (unsigned long) request);
|
||||
DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -1059,11 +1059,12 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
|
||||
lock_kernel(); /* XXX for now */
|
||||
if (fn != NULL)
|
||||
ret = (*fn)(filp, cmd, arg);
|
||||
ret = (*fn) (filp, cmd, arg);
|
||||
else
|
||||
ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
|
||||
unlock_kernel();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_compat_ioctl);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_ioctl.h
|
||||
* \file drm_ioctl.c
|
||||
* IOCTL processing for DRM
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
/**
|
||||
* Get the bus id.
|
||||
*
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
|
@ -50,12 +50,12 @@
|
|||
* Copies the bus id from drm_device::unique into user space.
|
||||
*/
|
||||
int drm_getunique(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_unique_t __user *argp = (void __user *)arg;
|
||||
drm_unique_t u;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_unique_t __user *argp = (void __user *)arg;
|
||||
drm_unique_t u;
|
||||
|
||||
if (copy_from_user(&u, argp, sizeof(u)))
|
||||
return -EFAULT;
|
||||
|
@ -71,7 +71,7 @@ int drm_getunique(struct inode *inode, struct file *filp,
|
|||
|
||||
/**
|
||||
* Set the bus id.
|
||||
*
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
|
@ -84,34 +84,39 @@ int drm_getunique(struct inode *inode, struct file *filp,
|
|||
* version 1.1 or greater.
|
||||
*/
|
||||
int drm_setunique(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_unique_t u;
|
||||
int domain, bus, slot, func, ret;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_unique_t u;
|
||||
int domain, bus, slot, func, ret;
|
||||
|
||||
if (dev->unique_len || dev->unique) return -EBUSY;
|
||||
if (dev->unique_len || dev->unique)
|
||||
return -EBUSY;
|
||||
|
||||
if (copy_from_user(&u, (drm_unique_t __user *)arg, sizeof(u)))
|
||||
if (copy_from_user(&u, (drm_unique_t __user *) arg, sizeof(u)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
|
||||
if (!u.unique_len || u.unique_len > 1024)
|
||||
return -EINVAL;
|
||||
|
||||
dev->unique_len = u.unique_len;
|
||||
dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
|
||||
if(!dev->unique) return -ENOMEM;
|
||||
dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
|
||||
if (!dev->unique)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(dev->unique, u.unique, dev->unique_len))
|
||||
return -EFAULT;
|
||||
|
||||
dev->unique[dev->unique_len] = '\0';
|
||||
|
||||
dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + strlen(dev->unique) + 2,
|
||||
DRM_MEM_DRIVER);
|
||||
dev->devname =
|
||||
drm_alloc(strlen(dev->driver->pci_driver.name) +
|
||||
strlen(dev->unique) + 2, DRM_MEM_DRIVER);
|
||||
if (!dev->devname)
|
||||
return -ENOMEM;
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique);
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
|
||||
dev->unique);
|
||||
|
||||
/* Return error if the busid submitted doesn't match the device's actual
|
||||
* busid.
|
||||
|
@ -121,18 +126,16 @@ int drm_setunique(struct inode *inode, struct file *filp,
|
|||
return DRM_ERR(EINVAL);
|
||||
domain = bus >> 8;
|
||||
bus &= 0xff;
|
||||
|
||||
|
||||
if ((domain != dev->pci_domain) ||
|
||||
(bus != dev->pci_bus) ||
|
||||
(slot != dev->pci_slot) ||
|
||||
(func != dev->pci_func))
|
||||
(slot != dev->pci_slot) || (func != dev->pci_func))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_set_busid(drm_device_t *dev)
|
||||
static int drm_set_busid(drm_device_t * dev)
|
||||
{
|
||||
if (dev->unique != NULL)
|
||||
return EBUSY;
|
||||
|
@ -143,19 +146,20 @@ drm_set_busid(drm_device_t *dev)
|
|||
return ENOMEM;
|
||||
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
|
||||
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
|
||||
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
|
||||
|
||||
dev->devname = drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + 2,
|
||||
DRM_MEM_DRIVER);
|
||||
dev->devname =
|
||||
drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
|
||||
2, DRM_MEM_DRIVER);
|
||||
if (dev->devname == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, dev->unique);
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
|
||||
dev->unique);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a mapping information.
|
||||
*
|
||||
|
@ -163,23 +167,23 @@ drm_set_busid(drm_device_t *dev)
|
|||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_map structure.
|
||||
*
|
||||
*
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Searches for the mapping with the specified offset and copies its information
|
||||
* into userspace
|
||||
*/
|
||||
int drm_getmap( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_getmap(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_map_t __user *argp = (void __user *)arg;
|
||||
drm_map_t map;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_map_t __user *argp = (void __user *)arg;
|
||||
drm_map_t map;
|
||||
drm_map_list_t *r_list = NULL;
|
||||
struct list_head *list;
|
||||
int idx;
|
||||
int i;
|
||||
int idx;
|
||||
int i;
|
||||
|
||||
if (copy_from_user(&map, argp, sizeof(map)))
|
||||
return -EFAULT;
|
||||
|
@ -193,26 +197,27 @@ int drm_getmap( struct inode *inode, struct file *filp,
|
|||
|
||||
i = 0;
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
if(i == idx) {
|
||||
if (i == idx) {
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(!r_list || !r_list->map) {
|
||||
if (!r_list || !r_list->map) {
|
||||
up(&dev->struct_sem);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map.offset = r_list->map->offset;
|
||||
map.size = r_list->map->size;
|
||||
map.type = r_list->map->type;
|
||||
map.flags = r_list->map->flags;
|
||||
map.handle = (void *)(unsigned long) r_list->user_token;
|
||||
map.mtrr = r_list->map->mtrr;
|
||||
map.size = r_list->map->size;
|
||||
map.type = r_list->map->type;
|
||||
map.flags = r_list->map->flags;
|
||||
map.handle = (void *)(unsigned long)r_list->user_token;
|
||||
map.mtrr = r_list->map->mtrr;
|
||||
up(&dev->struct_sem);
|
||||
|
||||
if (copy_to_user(argp, &map, sizeof(map))) return -EFAULT;
|
||||
if (copy_to_user(argp, &map, sizeof(map)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -223,83 +228,81 @@ int drm_getmap( struct inode *inode, struct file *filp,
|
|||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_client structure.
|
||||
*
|
||||
*
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Searches for the client with the specified index and copies its information
|
||||
* into userspace
|
||||
*/
|
||||
int drm_getclient( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_getclient(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_client_t __user *argp = (void __user *)arg;
|
||||
drm_client_t client;
|
||||
drm_file_t *pt;
|
||||
int idx;
|
||||
int i;
|
||||
drm_file_t *pt;
|
||||
int idx;
|
||||
int i;
|
||||
|
||||
if (copy_from_user(&client, argp, sizeof(client)))
|
||||
return -EFAULT;
|
||||
idx = client.idx;
|
||||
down(&dev->struct_sem);
|
||||
for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
|
||||
;
|
||||
for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
|
||||
|
||||
if (!pt) {
|
||||
up(&dev->struct_sem);
|
||||
return -EINVAL;
|
||||
}
|
||||
client.auth = pt->authenticated;
|
||||
client.pid = pt->pid;
|
||||
client.uid = pt->uid;
|
||||
client.auth = pt->authenticated;
|
||||
client.pid = pt->pid;
|
||||
client.uid = pt->uid;
|
||||
client.magic = pt->magic;
|
||||
client.iocs = pt->ioctl_count;
|
||||
client.iocs = pt->ioctl_count;
|
||||
up(&dev->struct_sem);
|
||||
|
||||
if (copy_to_user((drm_client_t __user *)arg, &client, sizeof(client)))
|
||||
if (copy_to_user((drm_client_t __user *) arg, &client, sizeof(client)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get statistics information.
|
||||
*
|
||||
/**
|
||||
* Get statistics information.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_stats structure.
|
||||
*
|
||||
*
|
||||
* \return zero on success or a negative number on failure.
|
||||
*/
|
||||
int drm_getstats( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_getstats(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_stats_t stats;
|
||||
int i;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_stats_t stats;
|
||||
int i;
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
|
||||
down(&dev->struct_sem);
|
||||
|
||||
for (i = 0; i < dev->counters; i++) {
|
||||
if (dev->types[i] == _DRM_STAT_LOCK)
|
||||
stats.data[i].value
|
||||
= (dev->lock.hw_lock
|
||||
? dev->lock.hw_lock->lock : 0);
|
||||
else
|
||||
= (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
|
||||
else
|
||||
stats.data[i].value = atomic_read(&dev->counts[i]);
|
||||
stats.data[i].type = dev->types[i];
|
||||
stats.data[i].type = dev->types[i];
|
||||
}
|
||||
|
||||
|
||||
stats.count = dev->counters;
|
||||
|
||||
up(&dev->struct_sem);
|
||||
|
||||
if (copy_to_user((drm_stats_t __user *)arg, &stats, sizeof(stats)))
|
||||
if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -352,7 +355,8 @@ int drm_setversion(DRM_IOCTL_ARGS)
|
|||
|
||||
if (sv.drm_dd_major != -1) {
|
||||
if (sv.drm_dd_major != version.version_major ||
|
||||
sv.drm_dd_minor < 0 || sv.drm_dd_minor > version.version_minor)
|
||||
sv.drm_dd_minor < 0
|
||||
|| sv.drm_dd_minor > version.version_minor)
|
||||
return EINVAL;
|
||||
|
||||
if (dev->driver->set_version)
|
||||
|
@ -363,7 +367,7 @@ int drm_setversion(DRM_IOCTL_ARGS)
|
|||
|
||||
/** No-op ioctl. */
|
||||
int drm_noop(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
return 0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_irq.h
|
||||
* \file drm_irq.c
|
||||
* IRQ support
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -39,19 +39,19 @@
|
|||
|
||||
/**
|
||||
* Get interrupt from bus id.
|
||||
*
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param filp file pointer.
|
||||
* \param cmd command.
|
||||
* \param arg user argument, pointing to a drm_irq_busid structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
*
|
||||
* Finds the PCI device with the specified bus id and gets its IRQ number.
|
||||
* This IOCTL is deprecated, and will now return EINVAL for any busid not equal
|
||||
* to that of the device that this DRM instance attached to.
|
||||
*/
|
||||
int drm_irq_by_busid(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
@ -66,14 +66,12 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
|
|||
|
||||
if ((p.busnum >> 8) != dev->pci_domain ||
|
||||
(p.busnum & 0xff) != dev->pci_bus ||
|
||||
p.devnum != dev->pci_slot ||
|
||||
p.funcnum != dev->pci_func)
|
||||
p.devnum != dev->pci_slot || p.funcnum != dev->pci_func)
|
||||
return -EINVAL;
|
||||
|
||||
p.irq = dev->irq;
|
||||
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
p.busnum, p.devnum, p.funcnum, p.irq);
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq);
|
||||
if (copy_to_user(argp, &p, sizeof(p)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
@ -89,61 +87,61 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
|
|||
* \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
|
||||
* before and after the installation.
|
||||
*/
|
||||
static int drm_irq_install( drm_device_t *dev )
|
||||
static int drm_irq_install(drm_device_t * dev)
|
||||
{
|
||||
int ret;
|
||||
unsigned long sh_flags=0;
|
||||
unsigned long sh_flags = 0;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return -EINVAL;
|
||||
|
||||
if ( dev->irq == 0 )
|
||||
if (dev->irq == 0)
|
||||
return -EINVAL;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
down(&dev->struct_sem);
|
||||
|
||||
/* Driver must have been initialized */
|
||||
if ( !dev->dev_private ) {
|
||||
up( &dev->struct_sem );
|
||||
if (!dev->dev_private) {
|
||||
up(&dev->struct_sem);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( dev->irq_enabled ) {
|
||||
up( &dev->struct_sem );
|
||||
if (dev->irq_enabled) {
|
||||
up(&dev->struct_sem);
|
||||
return -EBUSY;
|
||||
}
|
||||
dev->irq_enabled = 1;
|
||||
up( &dev->struct_sem );
|
||||
up(&dev->struct_sem);
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
|
||||
init_waitqueue_head(&dev->vbl_queue);
|
||||
|
||||
spin_lock_init( &dev->vbl_lock );
|
||||
|
||||
INIT_LIST_HEAD( &dev->vbl_sigs.head );
|
||||
|
||||
|
||||
spin_lock_init(&dev->vbl_lock);
|
||||
|
||||
INIT_LIST_HEAD(&dev->vbl_sigs.head);
|
||||
|
||||
dev->vbl_pending = 0;
|
||||
}
|
||||
|
||||
/* Before installing handler */
|
||||
/* Before installing handler */
|
||||
dev->driver->irq_preinstall(dev);
|
||||
|
||||
/* Install handler */
|
||||
/* Install handler */
|
||||
if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
|
||||
sh_flags = SA_SHIRQ;
|
||||
|
||||
ret = request_irq( dev->irq, dev->driver->irq_handler,
|
||||
sh_flags, dev->devname, dev );
|
||||
if ( ret < 0 ) {
|
||||
down( &dev->struct_sem );
|
||||
|
||||
ret = request_irq(dev->irq, dev->driver->irq_handler,
|
||||
sh_flags, dev->devname, dev);
|
||||
if (ret < 0) {
|
||||
down(&dev->struct_sem);
|
||||
dev->irq_enabled = 0;
|
||||
up( &dev->struct_sem );
|
||||
up(&dev->struct_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* After installing handler */
|
||||
/* After installing handler */
|
||||
dev->driver->irq_postinstall(dev);
|
||||
|
||||
return 0;
|
||||
|
@ -156,29 +154,30 @@ static int drm_irq_install( drm_device_t *dev )
|
|||
*
|
||||
* Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
|
||||
*/
|
||||
int drm_irq_uninstall( drm_device_t *dev )
|
||||
int drm_irq_uninstall(drm_device_t * dev)
|
||||
{
|
||||
int irq_enabled;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return -EINVAL;
|
||||
|
||||
down( &dev->struct_sem );
|
||||
down(&dev->struct_sem);
|
||||
irq_enabled = dev->irq_enabled;
|
||||
dev->irq_enabled = 0;
|
||||
up( &dev->struct_sem );
|
||||
up(&dev->struct_sem);
|
||||
|
||||
if ( !irq_enabled )
|
||||
if (!irq_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq);
|
||||
|
||||
dev->driver->irq_uninstall(dev);
|
||||
|
||||
free_irq( dev->irq, dev );
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_irq_uninstall);
|
||||
|
||||
/**
|
||||
|
@ -192,30 +191,30 @@ EXPORT_SYMBOL(drm_irq_uninstall);
|
|||
*
|
||||
* Calls irq_install() or irq_uninstall() according to \p arg.
|
||||
*/
|
||||
int drm_control( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_control(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_control_t ctl;
|
||||
|
||||
|
||||
/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
|
||||
|
||||
if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
|
||||
if (copy_from_user(&ctl, (drm_control_t __user *) arg, sizeof(ctl)))
|
||||
return -EFAULT;
|
||||
|
||||
switch ( ctl.func ) {
|
||||
switch (ctl.func) {
|
||||
case DRM_INST_HANDLER:
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return 0;
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl.irq != dev->irq)
|
||||
return -EINVAL;
|
||||
return drm_irq_install( dev );
|
||||
return drm_irq_install(dev);
|
||||
case DRM_UNINST_HANDLER:
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return 0;
|
||||
return drm_irq_uninstall( dev );
|
||||
return drm_irq_uninstall(dev);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -230,7 +229,7 @@ int drm_control( struct inode *inode, struct file *filp,
|
|||
* \param data user argument, pointing to a drm_wait_vblank structure.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Verifies the IRQ is installed.
|
||||
* Verifies the IRQ is installed.
|
||||
*
|
||||
* If a signal is requested checks if this task has already scheduled the same signal
|
||||
* for the same vblank sequence number - nothing to be done in
|
||||
|
@ -240,7 +239,7 @@ int drm_control( struct inode *inode, struct file *filp,
|
|||
*
|
||||
* If a signal is not requested, then calls vblank_wait().
|
||||
*/
|
||||
int drm_wait_vblank( DRM_IOCTL_ARGS )
|
||||
int drm_wait_vblank(DRM_IOCTL_ARGS)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
@ -256,11 +255,11 @@ int drm_wait_vblank( DRM_IOCTL_ARGS )
|
|||
if (!dev->irq)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( vblwait, argp, sizeof(vblwait) );
|
||||
DRM_COPY_FROM_USER_IOCTL(vblwait, argp, sizeof(vblwait));
|
||||
|
||||
switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
|
||||
switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) {
|
||||
case _DRM_VBLANK_RELATIVE:
|
||||
vblwait.request.sequence += atomic_read( &dev->vbl_received );
|
||||
vblwait.request.sequence += atomic_read(&dev->vbl_received);
|
||||
vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
|
||||
case _DRM_VBLANK_ABSOLUTE:
|
||||
break;
|
||||
|
@ -269,64 +268,68 @@ int drm_wait_vblank( DRM_IOCTL_ARGS )
|
|||
}
|
||||
|
||||
flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
|
||||
|
||||
if ( flags & _DRM_VBLANK_SIGNAL ) {
|
||||
|
||||
if (flags & _DRM_VBLANK_SIGNAL) {
|
||||
unsigned long irqflags;
|
||||
drm_vbl_sig_t *vbl_sig;
|
||||
|
||||
vblwait.reply.sequence = atomic_read( &dev->vbl_received );
|
||||
|
||||
spin_lock_irqsave( &dev->vbl_lock, irqflags );
|
||||
vblwait.reply.sequence = atomic_read(&dev->vbl_received);
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
|
||||
/* Check if this task has already scheduled the same signal
|
||||
* for the same vblank sequence number; nothing to be done in
|
||||
* that case
|
||||
*/
|
||||
list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
|
||||
list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) {
|
||||
if (vbl_sig->sequence == vblwait.request.sequence
|
||||
&& vbl_sig->info.si_signo == vblwait.request.signal
|
||||
&& vbl_sig->task == current)
|
||||
{
|
||||
spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
|
||||
&& vbl_sig->task == current) {
|
||||
spin_unlock_irqrestore(&dev->vbl_lock,
|
||||
irqflags);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ( dev->vbl_pending >= 100 ) {
|
||||
spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
|
||||
if (dev->vbl_pending >= 100) {
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dev->vbl_pending++;
|
||||
|
||||
spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
if ( !( vbl_sig = drm_alloc( sizeof( drm_vbl_sig_t ), DRM_MEM_DRIVER ) ) ) {
|
||||
if (!
|
||||
(vbl_sig =
|
||||
drm_alloc(sizeof(drm_vbl_sig_t), DRM_MEM_DRIVER))) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
|
||||
memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
|
||||
|
||||
vbl_sig->sequence = vblwait.request.sequence;
|
||||
vbl_sig->info.si_signo = vblwait.request.signal;
|
||||
vbl_sig->task = current;
|
||||
|
||||
spin_lock_irqsave( &dev->vbl_lock, irqflags );
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
|
||||
list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
|
||||
list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head);
|
||||
|
||||
spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
} else {
|
||||
if (dev->driver->vblank_wait)
|
||||
ret = dev->driver->vblank_wait( dev, &vblwait.request.sequence );
|
||||
ret =
|
||||
dev->driver->vblank_wait(dev,
|
||||
&vblwait.request.sequence);
|
||||
|
||||
do_gettimeofday( &now );
|
||||
do_gettimeofday(&now);
|
||||
vblwait.reply.tval_sec = now.tv_sec;
|
||||
vblwait.reply.tval_usec = now.tv_usec;
|
||||
}
|
||||
|
||||
done:
|
||||
DRM_COPY_TO_USER_IOCTL( argp, vblwait, sizeof(vblwait) );
|
||||
done:
|
||||
DRM_COPY_TO_USER_IOCTL(argp, vblwait, sizeof(vblwait));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -340,31 +343,31 @@ done:
|
|||
*
|
||||
* If a signal is not requested, then calls vblank_wait().
|
||||
*/
|
||||
void drm_vbl_send_signals( drm_device_t *dev )
|
||||
void drm_vbl_send_signals(drm_device_t * dev)
|
||||
{
|
||||
struct list_head *list, *tmp;
|
||||
drm_vbl_sig_t *vbl_sig;
|
||||
unsigned int vbl_seq = atomic_read( &dev->vbl_received );
|
||||
unsigned int vbl_seq = atomic_read(&dev->vbl_received);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave( &dev->vbl_lock, flags );
|
||||
spin_lock_irqsave(&dev->vbl_lock, flags);
|
||||
|
||||
list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
|
||||
vbl_sig = list_entry( list, drm_vbl_sig_t, head );
|
||||
if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
|
||||
list_for_each_safe(list, tmp, &dev->vbl_sigs.head) {
|
||||
vbl_sig = list_entry(list, drm_vbl_sig_t, head);
|
||||
if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
|
||||
vbl_sig->info.si_code = vbl_seq;
|
||||
send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
|
||||
send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info,
|
||||
vbl_sig->task);
|
||||
|
||||
list_del( list );
|
||||
list_del(list);
|
||||
|
||||
drm_free( vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER );
|
||||
drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER);
|
||||
|
||||
dev->vbl_pending--;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore( &dev->vbl_lock, flags );
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_vbl_send_signals);
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* \file drm_lock.h
|
||||
* \file drm_lock.c
|
||||
* IOCTLs for locking
|
||||
*
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
@ -35,12 +35,12 @@
|
|||
|
||||
#include "drmP.h"
|
||||
|
||||
static int drm_lock_transfer(drm_device_t *dev,
|
||||
static int drm_lock_transfer(drm_device_t * dev,
|
||||
__volatile__ unsigned int *lock,
|
||||
unsigned int context);
|
||||
static int drm_notifier(void *priv);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Lock ioctl.
|
||||
*
|
||||
* \param inode device inode.
|
||||
|
@ -51,91 +51,89 @@ static int drm_notifier(void *priv);
|
|||
*
|
||||
* Add the current task to the lock wait queue, and attempt to take to lock.
|
||||
*/
|
||||
int drm_lock( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_lock(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
DECLARE_WAITQUEUE( entry, current );
|
||||
drm_lock_t lock;
|
||||
int ret = 0;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
drm_lock_t lock;
|
||||
int ret = 0;
|
||||
|
||||
++priv->lock_count;
|
||||
|
||||
if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
|
||||
if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
|
||||
return -EFAULT;
|
||||
|
||||
if ( lock.context == DRM_KERNEL_CONTEXT ) {
|
||||
DRM_ERROR( "Process %d using kernel context %d\n",
|
||||
current->pid, lock.context );
|
||||
return -EINVAL;
|
||||
}
|
||||
if (lock.context == DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Process %d using kernel context %d\n",
|
||||
current->pid, lock.context);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
|
||||
lock.context, current->pid,
|
||||
dev->lock.hw_lock->lock, lock.flags );
|
||||
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
|
||||
lock.context, current->pid,
|
||||
dev->lock.hw_lock->lock, lock.flags);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
|
||||
if ( lock.context < 0 )
|
||||
if (lock.context < 0)
|
||||
return -EINVAL;
|
||||
|
||||
add_wait_queue( &dev->lock.lock_queue, &entry );
|
||||
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
for (;;) {
|
||||
__set_current_state(TASK_INTERRUPTIBLE);
|
||||
if ( !dev->lock.hw_lock ) {
|
||||
if (!dev->lock.hw_lock) {
|
||||
/* Device has been unregistered */
|
||||
ret = -EINTR;
|
||||
break;
|
||||
}
|
||||
if ( drm_lock_take( &dev->lock.hw_lock->lock,
|
||||
lock.context ) ) {
|
||||
dev->lock.filp = filp;
|
||||
if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) {
|
||||
dev->lock.filp = filp;
|
||||
dev->lock.lock_time = jiffies;
|
||||
atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
|
||||
break; /* Got lock */
|
||||
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
|
||||
break; /* Got lock */
|
||||
}
|
||||
|
||||
|
||||
/* Contention */
|
||||
schedule();
|
||||
if ( signal_pending( current ) ) {
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue( &dev->lock.lock_queue, &entry );
|
||||
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
|
||||
sigemptyset( &dev->sigmask );
|
||||
sigaddset( &dev->sigmask, SIGSTOP );
|
||||
sigaddset( &dev->sigmask, SIGTSTP );
|
||||
sigaddset( &dev->sigmask, SIGTTIN );
|
||||
sigaddset( &dev->sigmask, SIGTTOU );
|
||||
sigemptyset(&dev->sigmask);
|
||||
sigaddset(&dev->sigmask, SIGSTOP);
|
||||
sigaddset(&dev->sigmask, SIGTSTP);
|
||||
sigaddset(&dev->sigmask, SIGTTIN);
|
||||
sigaddset(&dev->sigmask, SIGTTOU);
|
||||
dev->sigdata.context = lock.context;
|
||||
dev->sigdata.lock = dev->lock.hw_lock;
|
||||
block_all_signals( drm_notifier,
|
||||
&dev->sigdata, &dev->sigmask );
|
||||
|
||||
dev->sigdata.lock = dev->lock.hw_lock;
|
||||
block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
|
||||
|
||||
if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY))
|
||||
dev->driver->dma_ready(dev);
|
||||
|
||||
if ( dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
|
||||
|
||||
if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT))
|
||||
return dev->driver->dma_quiescent(dev);
|
||||
|
||||
/* dev->driver->kernel_context_switch isn't used by any of the x86
|
||||
|
||||
/* dev->driver->kernel_context_switch isn't used by any of the x86
|
||||
* drivers but is used by the Sparc driver.
|
||||
*/
|
||||
|
||||
if (dev->driver->kernel_context_switch &&
|
||||
dev->last_context != lock.context) {
|
||||
dev->driver->kernel_context_switch(dev, dev->last_context,
|
||||
lock.context);
|
||||
}
|
||||
DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
|
||||
|
||||
return ret;
|
||||
if (dev->driver->kernel_context_switch &&
|
||||
dev->last_context != lock.context) {
|
||||
dev->driver->kernel_context_switch(dev, dev->last_context,
|
||||
lock.context);
|
||||
}
|
||||
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Unlock ioctl.
|
||||
*
|
||||
* \param inode device inode.
|
||||
|
@ -146,23 +144,23 @@ int drm_lock( struct inode *inode, struct file *filp,
|
|||
*
|
||||
* Transfer and free the lock.
|
||||
*/
|
||||
int drm_unlock( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_unlock(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_lock_t lock;
|
||||
|
||||
if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
|
||||
if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
|
||||
return -EFAULT;
|
||||
|
||||
if ( lock.context == DRM_KERNEL_CONTEXT ) {
|
||||
DRM_ERROR( "Process %d using kernel context %d\n",
|
||||
current->pid, lock.context );
|
||||
if (lock.context == DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Process %d using kernel context %d\n",
|
||||
current->pid, lock.context);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
|
||||
atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
|
||||
|
||||
/* kernel_context_switch isn't used by any of the x86 drm
|
||||
* modules but is required by the Sparc driver.
|
||||
|
@ -170,12 +168,12 @@ int drm_unlock( struct inode *inode, struct file *filp,
|
|||
if (dev->driver->kernel_context_switch_unlock)
|
||||
dev->driver->kernel_context_switch_unlock(dev, &lock);
|
||||
else {
|
||||
drm_lock_transfer( dev, &dev->lock.hw_lock->lock,
|
||||
DRM_KERNEL_CONTEXT );
|
||||
|
||||
if ( drm_lock_free( dev, &dev->lock.hw_lock->lock,
|
||||
DRM_KERNEL_CONTEXT ) ) {
|
||||
DRM_ERROR( "\n" );
|
||||
drm_lock_transfer(dev, &dev->lock.hw_lock->lock,
|
||||
DRM_KERNEL_CONTEXT);
|
||||
|
||||
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
|
||||
DRM_KERNEL_CONTEXT)) {
|
||||
DRM_ERROR("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,8 +196,10 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
|
|||
|
||||
do {
|
||||
old = *lock;
|
||||
if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
|
||||
else new = context | _DRM_LOCK_HELD;
|
||||
if (old & _DRM_LOCK_HELD)
|
||||
new = old | _DRM_LOCK_CONT;
|
||||
else
|
||||
new = context | _DRM_LOCK_HELD;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
||||
|
@ -212,7 +212,7 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
|
|||
}
|
||||
}
|
||||
if (new == (context | _DRM_LOCK_HELD)) {
|
||||
/* Have lock */
|
||||
/* Have lock */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -220,8 +220,8 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
|
|||
|
||||
/**
|
||||
* This takes a lock forcibly and hands it to context. Should ONLY be used
|
||||
* inside *_unlock to give lock to kernel before calling *_dma_schedule.
|
||||
*
|
||||
* inside *_unlock to give lock to kernel before calling *_dma_schedule.
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param lock lock pointer.
|
||||
* \param context locking context.
|
||||
|
@ -230,7 +230,7 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
|
|||
* Resets the lock file pointer.
|
||||
* Marks the lock as held by the given context, via the \p cmpxchg instruction.
|
||||
*/
|
||||
static int drm_lock_transfer(drm_device_t *dev,
|
||||
static int drm_lock_transfer(drm_device_t * dev,
|
||||
__volatile__ unsigned int *lock,
|
||||
unsigned int context)
|
||||
{
|
||||
|
@ -238,8 +238,8 @@ static int drm_lock_transfer(drm_device_t *dev,
|
|||
|
||||
dev->lock.filp = NULL;
|
||||
do {
|
||||
old = *lock;
|
||||
new = context | _DRM_LOCK_HELD;
|
||||
old = *lock;
|
||||
new = context | _DRM_LOCK_HELD;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
return 1;
|
||||
|
@ -247,30 +247,29 @@ static int drm_lock_transfer(drm_device_t *dev,
|
|||
|
||||
/**
|
||||
* Free lock.
|
||||
*
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param lock lock.
|
||||
* \param context context.
|
||||
*
|
||||
*
|
||||
* Resets the lock file pointer.
|
||||
* Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
|
||||
* waiting on the lock queue.
|
||||
*/
|
||||
int drm_lock_free(drm_device_t *dev,
|
||||
__volatile__ unsigned int *lock, unsigned int context)
|
||||
int drm_lock_free(drm_device_t * dev,
|
||||
__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
|
||||
dev->lock.filp = NULL;
|
||||
do {
|
||||
old = *lock;
|
||||
new = 0;
|
||||
old = *lock;
|
||||
new = 0;
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
|
||||
DRM_ERROR("%d freed heavyweight lock held by %d\n",
|
||||
context,
|
||||
_DRM_LOCKING_CONTEXT(old));
|
||||
context, _DRM_LOCKING_CONTEXT(old));
|
||||
return 1;
|
||||
}
|
||||
wake_up_interruptible(&dev->lock.lock_queue);
|
||||
|
@ -290,19 +289,19 @@ int drm_lock_free(drm_device_t *dev,
|
|||
*/
|
||||
static int drm_notifier(void *priv)
|
||||
{
|
||||
drm_sigdata_t *s = (drm_sigdata_t *)priv;
|
||||
unsigned int old, new, prev;
|
||||
drm_sigdata_t *s = (drm_sigdata_t *) priv;
|
||||
unsigned int old, new, prev;
|
||||
|
||||
|
||||
/* Allow signal delivery if lock isn't held */
|
||||
/* Allow signal delivery if lock isn't held */
|
||||
if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
|
||||
|| _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
|
||||
|| _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context)
|
||||
return 1;
|
||||
|
||||
/* Otherwise, set flag to force call to
|
||||
drmUnlock */
|
||||
/* Otherwise, set flag to force call to
|
||||
drmUnlock */
|
||||
do {
|
||||
old = s->lock->lock;
|
||||
new = old | _DRM_LOCK_CONT;
|
||||
old = s->lock->lock;
|
||||
new = old | _DRM_LOCK_CONT;
|
||||
prev = cmpxchg(&s->lock->lock, old, new);
|
||||
} while (prev != old);
|
||||
return 0;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/**
|
||||
* \file drm_memory.h
|
||||
/**
|
||||
* \file drm_memory.c
|
||||
* Memory management wrappers for DRM
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
|
@ -48,7 +48,7 @@ void drm_mem_init(void)
|
|||
|
||||
/**
|
||||
* Called when "/proc/dri/%dev%/mem" is read.
|
||||
*
|
||||
*
|
||||
* \param buf output buffer.
|
||||
* \param start start of output data.
|
||||
* \param offset requested start offset.
|
||||
|
@ -57,10 +57,10 @@ void drm_mem_init(void)
|
|||
* \param data private data.
|
||||
* \return number of written bytes.
|
||||
*
|
||||
* No-op.
|
||||
* No-op.
|
||||
*/
|
||||
int drm_mem_info(char *buf, char **start, off_t offset,
|
||||
int len, int *eof, void *data)
|
||||
int len, int *eof, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -70,7 +70,8 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
|
|||
{
|
||||
void *pt;
|
||||
|
||||
if (!(pt = kmalloc(size, GFP_KERNEL))) return NULL;
|
||||
if (!(pt = kmalloc(size, GFP_KERNEL)))
|
||||
return NULL;
|
||||
if (oldpt && oldsize) {
|
||||
memcpy(pt, oldpt, oldsize);
|
||||
kfree(oldpt);
|
||||
|
@ -90,21 +91,20 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
|
|||
unsigned long drm_alloc_pages(int order, int area)
|
||||
{
|
||||
unsigned long address;
|
||||
unsigned long bytes = PAGE_SIZE << order;
|
||||
unsigned long bytes = PAGE_SIZE << order;
|
||||
unsigned long addr;
|
||||
unsigned int sz;
|
||||
unsigned int sz;
|
||||
|
||||
address = __get_free_pages(GFP_KERNEL, order);
|
||||
if (!address)
|
||||
if (!address)
|
||||
return 0;
|
||||
|
||||
/* Zero */
|
||||
/* Zero */
|
||||
memset((void *)address, 0, bytes);
|
||||
|
||||
/* Reserve */
|
||||
/* Reserve */
|
||||
for (addr = address, sz = bytes;
|
||||
sz > 0;
|
||||
addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||
SetPageReserved(virt_to_page(addr));
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ unsigned long drm_alloc_pages(int order, int area)
|
|||
|
||||
/**
|
||||
* Free pages.
|
||||
*
|
||||
*
|
||||
* \param address address of the pages to free.
|
||||
* \param order size order.
|
||||
* \param area memory area. (Not used.)
|
||||
|
@ -124,49 +124,51 @@ void drm_free_pages(unsigned long address, int order, int area)
|
|||
{
|
||||
unsigned long bytes = PAGE_SIZE << order;
|
||||
unsigned long addr;
|
||||
unsigned int sz;
|
||||
unsigned int sz;
|
||||
|
||||
if (!address)
|
||||
if (!address)
|
||||
return;
|
||||
|
||||
/* Unreserve */
|
||||
for (addr = address, sz = bytes;
|
||||
sz > 0;
|
||||
addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page(addr));
|
||||
}
|
||||
|
||||
free_pages(address, order);
|
||||
}
|
||||
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
/** Wrapper around agp_allocate_memory() */
|
||||
DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type)
|
||||
DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
|
||||
{
|
||||
return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_alloc_agp);
|
||||
|
||||
/** Wrapper around agp_free_memory() */
|
||||
int drm_free_agp(DRM_AGP_MEM *handle, int pages)
|
||||
int drm_free_agp(DRM_AGP_MEM * handle, int pages)
|
||||
{
|
||||
return drm_agp_free_memory(handle) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_free_agp);
|
||||
|
||||
/** Wrapper around agp_bind_memory() */
|
||||
int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start)
|
||||
int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
|
||||
{
|
||||
return drm_agp_bind_memory(handle, start);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_bind_agp);
|
||||
|
||||
/** Wrapper around agp_unbind_memory() */
|
||||
int drm_unbind_agp(DRM_AGP_MEM *handle)
|
||||
int drm_unbind_agp(DRM_AGP_MEM * handle)
|
||||
{
|
||||
return drm_agp_unbind_memory(handle);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_unbind_agp);
|
||||
#endif /* agp */
|
||||
#endif /* debug_memory */
|
||||
#endif /* agp */
|
||||
#endif /* debug_memory */
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/**
|
||||
* \file drm_memory.h
|
||||
/**
|
||||
* \file drm_memory.h
|
||||
* Memory management wrappers for DRM
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
/**
|
||||
* Cut down version of drm_memory_debug.h, which used to be called
|
||||
* drm_memory.h.
|
||||
* drm_memory.h.
|
||||
*/
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
|
@ -60,8 +60,8 @@
|
|||
/*
|
||||
* Find the drm_map that covers the range [offset, offset+size).
|
||||
*/
|
||||
static inline drm_map_t *
|
||||
drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev)
|
||||
static inline drm_map_t *drm_lookup_map(unsigned long offset,
|
||||
unsigned long size, drm_device_t * dev)
|
||||
{
|
||||
struct list_head *list;
|
||||
drm_map_list_t *r_list;
|
||||
|
@ -72,16 +72,18 @@ drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev)
|
|||
map = r_list->map;
|
||||
if (!map)
|
||||
continue;
|
||||
if (map->offset <= offset && (offset + size) <= (map->offset + map->size))
|
||||
if (map->offset <= offset
|
||||
&& (offset + size) <= (map->offset + map->size))
|
||||
return map;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
|
||||
static inline void *agp_remap(unsigned long offset, unsigned long size,
|
||||
drm_device_t * dev)
|
||||
{
|
||||
unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE;
|
||||
unsigned long *phys_addr_map, i, num_pages =
|
||||
PAGE_ALIGN(size) / PAGE_SIZE;
|
||||
struct drm_agp_mem *agpmem;
|
||||
struct page **page_map;
|
||||
void *addr;
|
||||
|
@ -94,7 +96,8 @@ agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
|
|||
|
||||
for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
|
||||
if (agpmem->bound <= offset
|
||||
&& (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size))
|
||||
&& (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
|
||||
(offset + size))
|
||||
break;
|
||||
if (!agpmem)
|
||||
return NULL;
|
||||
|
@ -109,7 +112,8 @@ agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
|
|||
if (!page_map)
|
||||
return NULL;
|
||||
|
||||
phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
|
||||
phys_addr_map =
|
||||
agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
|
||||
for (i = 0; i < num_pages; ++i)
|
||||
page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
|
||||
addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
|
||||
|
@ -118,36 +122,38 @@ agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
|
|||
return addr;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
drm_follow_page (void *vaddr)
|
||||
static inline unsigned long drm_follow_page(void *vaddr)
|
||||
{
|
||||
pgd_t *pgd = pgd_offset_k((unsigned long) vaddr);
|
||||
pud_t *pud = pud_offset(pgd, (unsigned long) vaddr);
|
||||
pmd_t *pmd = pmd_offset(pud, (unsigned long) vaddr);
|
||||
pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr);
|
||||
pgd_t *pgd = pgd_offset_k((unsigned long)vaddr);
|
||||
pud_t *pud = pud_offset(pgd, (unsigned long)vaddr);
|
||||
pmd_t *pmd = pmd_offset(pud, (unsigned long)vaddr);
|
||||
pte_t *ptep = pte_offset_kernel(pmd, (unsigned long)vaddr);
|
||||
return pte_pfn(*ptep) << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
#else /* __OS_HAS_AGP */
|
||||
#else /* __OS_HAS_AGP */
|
||||
|
||||
static inline drm_map_t *drm_lookup_map(unsigned long offset, unsigned long size, drm_device_t *dev)
|
||||
static inline drm_map_t *drm_lookup_map(unsigned long offset,
|
||||
unsigned long size, drm_device_t * dev)
|
||||
{
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t *dev)
|
||||
static inline void *agp_remap(unsigned long offset, unsigned long size,
|
||||
drm_device_t * dev)
|
||||
{
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline unsigned long drm_follow_page (void *vaddr)
|
||||
static inline unsigned long drm_follow_page(void *vaddr)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
|
||||
static inline void *drm_ioremap(unsigned long offset, unsigned long size,
|
||||
drm_device_t * dev)
|
||||
{
|
||||
if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
|
||||
drm_map_t *map = drm_lookup_map(offset, size, dev);
|
||||
|
@ -158,8 +164,8 @@ static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_de
|
|||
return ioremap(offset, size);
|
||||
}
|
||||
|
||||
static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
|
||||
drm_device_t *dev)
|
||||
static inline void *drm_ioremap_nocache(unsigned long offset,
|
||||
unsigned long size, drm_device_t * dev)
|
||||
{
|
||||
if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
|
||||
drm_map_t *map = drm_lookup_map(offset, size, dev);
|
||||
|
@ -170,7 +176,8 @@ static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size
|
|||
return ioremap_nocache(offset, size);
|
||||
}
|
||||
|
||||
static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
|
||||
static inline void drm_ioremapfree(void *pt, unsigned long size,
|
||||
drm_device_t * dev)
|
||||
{
|
||||
/*
|
||||
* This is a bit ugly. It would be much cleaner if the DRM API would use separate
|
||||
|
@ -178,12 +185,12 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *d
|
|||
* a future revision of the interface...
|
||||
*/
|
||||
if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
|
||||
&& ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END))
|
||||
{
|
||||
&& ((unsigned long)pt >= VMALLOC_START
|
||||
&& (unsigned long)pt < VMALLOC_END)) {
|
||||
unsigned long offset;
|
||||
drm_map_t *map;
|
||||
|
||||
offset = drm_follow_page(pt) | ((unsigned long) pt & ~PAGE_MASK);
|
||||
offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
|
||||
map = drm_lookup_map(offset, size, dev);
|
||||
if (map && map->type == _DRM_AGP) {
|
||||
vunmap(pt);
|
||||
|
@ -193,5 +200,3 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *d
|
|||
|
||||
iounmap(pt);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_memory.h
|
||||
* \file drm_memory.h
|
||||
* Memory management wrappers for DRM.
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -35,75 +35,75 @@
|
|||
#include "drmP.h"
|
||||
|
||||
typedef struct drm_mem_stats {
|
||||
const char *name;
|
||||
int succeed_count;
|
||||
int free_count;
|
||||
int fail_count;
|
||||
unsigned long bytes_allocated;
|
||||
unsigned long bytes_freed;
|
||||
const char *name;
|
||||
int succeed_count;
|
||||
int free_count;
|
||||
int fail_count;
|
||||
unsigned long bytes_allocated;
|
||||
unsigned long bytes_freed;
|
||||
} drm_mem_stats_t;
|
||||
|
||||
static DEFINE_SPINLOCK(DRM(mem_lock));
|
||||
static unsigned long DRM(ram_available) = 0; /* In pages */
|
||||
static unsigned long DRM(ram_used) = 0;
|
||||
static drm_mem_stats_t DRM(mem_stats)[] = {
|
||||
[DRM_MEM_DMA] = { "dmabufs" },
|
||||
[DRM_MEM_SAREA] = { "sareas" },
|
||||
[DRM_MEM_DRIVER] = { "driver" },
|
||||
[DRM_MEM_MAGIC] = { "magic" },
|
||||
[DRM_MEM_IOCTLS] = { "ioctltab" },
|
||||
[DRM_MEM_MAPS] = { "maplist" },
|
||||
[DRM_MEM_VMAS] = { "vmalist" },
|
||||
[DRM_MEM_BUFS] = { "buflist" },
|
||||
[DRM_MEM_SEGS] = { "seglist" },
|
||||
[DRM_MEM_PAGES] = { "pagelist" },
|
||||
[DRM_MEM_FILES] = { "files" },
|
||||
[DRM_MEM_QUEUES] = { "queues" },
|
||||
[DRM_MEM_CMDS] = { "commands" },
|
||||
[DRM_MEM_MAPPINGS] = { "mappings" },
|
||||
[DRM_MEM_BUFLISTS] = { "buflists" },
|
||||
[DRM_MEM_AGPLISTS] = { "agplist" },
|
||||
[DRM_MEM_SGLISTS] = { "sglist" },
|
||||
[DRM_MEM_TOTALAGP] = { "totalagp" },
|
||||
[DRM_MEM_BOUNDAGP] = { "boundagp" },
|
||||
[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
|
||||
[DRM_MEM_CTXLIST] = { "ctxlist" },
|
||||
[DRM_MEM_STUB] = { "stub" },
|
||||
{ NULL, 0, } /* Last entry must be null */
|
||||
static unsigned long DRM(ram_available) = 0; /* In pages */
|
||||
static unsigned long DRM(ram_used) = 0;
|
||||
static drm_mem_stats_t DRM(mem_stats)[] =
|
||||
{
|
||||
[DRM_MEM_DMA] = {
|
||||
"dmabufs"},[DRM_MEM_SAREA] = {
|
||||
"sareas"},[DRM_MEM_DRIVER] = {
|
||||
"driver"},[DRM_MEM_MAGIC] = {
|
||||
"magic"},[DRM_MEM_IOCTLS] = {
|
||||
"ioctltab"},[DRM_MEM_MAPS] = {
|
||||
"maplist"},[DRM_MEM_VMAS] = {
|
||||
"vmalist"},[DRM_MEM_BUFS] = {
|
||||
"buflist"},[DRM_MEM_SEGS] = {
|
||||
"seglist"},[DRM_MEM_PAGES] = {
|
||||
"pagelist"},[DRM_MEM_FILES] = {
|
||||
"files"},[DRM_MEM_QUEUES] = {
|
||||
"queues"},[DRM_MEM_CMDS] = {
|
||||
"commands"},[DRM_MEM_MAPPINGS] = {
|
||||
"mappings"},[DRM_MEM_BUFLISTS] = {
|
||||
"buflists"},[DRM_MEM_AGPLISTS] = {
|
||||
"agplist"},[DRM_MEM_SGLISTS] = {
|
||||
"sglist"},[DRM_MEM_TOTALAGP] = {
|
||||
"totalagp"},[DRM_MEM_BOUNDAGP] = {
|
||||
"boundagp"},[DRM_MEM_CTXBITMAP] = {
|
||||
"ctxbitmap"},[DRM_MEM_CTXLIST] = {
|
||||
"ctxlist"},[DRM_MEM_STUB] = {
|
||||
"stub"}, {
|
||||
NULL, 0,} /* Last entry must be null */
|
||||
};
|
||||
|
||||
void DRM(mem_init)(void)
|
||||
{
|
||||
void DRM(mem_init) (void) {
|
||||
drm_mem_stats_t *mem;
|
||||
struct sysinfo si;
|
||||
struct sysinfo si;
|
||||
|
||||
for (mem = DRM(mem_stats); mem->name; ++mem) {
|
||||
mem->succeed_count = 0;
|
||||
mem->free_count = 0;
|
||||
mem->fail_count = 0;
|
||||
mem->succeed_count = 0;
|
||||
mem->free_count = 0;
|
||||
mem->fail_count = 0;
|
||||
mem->bytes_allocated = 0;
|
||||
mem->bytes_freed = 0;
|
||||
mem->bytes_freed = 0;
|
||||
}
|
||||
|
||||
si_meminfo(&si);
|
||||
DRM(ram_available) = si.totalram;
|
||||
DRM(ram_used) = 0;
|
||||
DRM(ram_used) = 0;
|
||||
}
|
||||
|
||||
/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
|
||||
|
||||
static int DRM(_mem_info)(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data)
|
||||
{
|
||||
static int DRM(_mem_info) (char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data) {
|
||||
drm_mem_stats_t *pt;
|
||||
int len = 0;
|
||||
int len = 0;
|
||||
|
||||
if (offset > DRM_PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*eof = 0;
|
||||
*eof = 0;
|
||||
*start = &buf[offset];
|
||||
|
||||
DRM_PROC_PRINT(" total counts "
|
||||
|
@ -129,24 +129,23 @@ static int DRM(_mem_info)(char *buf, char **start, off_t offset,
|
|||
- (long)pt->bytes_freed);
|
||||
}
|
||||
|
||||
if (len > request + offset) return request;
|
||||
if (len > request + offset)
|
||||
return request;
|
||||
*eof = 1;
|
||||
return len - offset;
|
||||
}
|
||||
|
||||
int DRM(mem_info)(char *buf, char **start, off_t offset,
|
||||
int len, int *eof, void *data)
|
||||
{
|
||||
int DRM(mem_info) (char *buf, char **start, off_t offset,
|
||||
int len, int *eof, void *data) {
|
||||
int ret;
|
||||
|
||||
spin_lock(&DRM(mem_lock));
|
||||
ret = DRM(_mem_info)(buf, start, offset, len, eof, data);
|
||||
ret = DRM(_mem_info) (buf, start, offset, len, eof, data);
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *DRM(alloc)(size_t size, int area)
|
||||
{
|
||||
void *DRM(alloc) (size_t size, int area) {
|
||||
void *pt;
|
||||
|
||||
if (!size) {
|
||||
|
@ -167,40 +166,40 @@ void *DRM(alloc)(size_t size, int area)
|
|||
return pt;
|
||||
}
|
||||
|
||||
void *DRM(calloc)(size_t nmemb, size_t size, int area)
|
||||
{
|
||||
void *DRM(calloc) (size_t nmemb, size_t size, int area) {
|
||||
void *addr;
|
||||
|
||||
addr = DRM(alloc)(nmemb * size, area);
|
||||
addr = DRM(alloc) (nmemb * size, area);
|
||||
if (addr != NULL)
|
||||
memset((void *)addr, 0, size * nmemb);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
|
||||
{
|
||||
void *DRM(realloc) (void *oldpt, size_t oldsize, size_t size, int area) {
|
||||
void *pt;
|
||||
|
||||
if (!(pt = DRM(alloc)(size, area))) return NULL;
|
||||
if (!(pt = DRM(alloc) (size, area)))
|
||||
return NULL;
|
||||
if (oldpt && oldsize) {
|
||||
memcpy(pt, oldpt, oldsize);
|
||||
DRM(free)(oldpt, oldsize, area);
|
||||
DRM(free) (oldpt, oldsize, area);
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
|
||||
void DRM(free)(void *pt, size_t size, int area)
|
||||
{
|
||||
void DRM(free) (void *pt, size_t size, int area) {
|
||||
int alloc_count;
|
||||
int free_count;
|
||||
|
||||
if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
|
||||
else kfree(pt);
|
||||
if (!pt)
|
||||
DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
|
||||
else
|
||||
kfree(pt);
|
||||
spin_lock(&DRM(mem_lock));
|
||||
DRM(mem_stats)[area].bytes_freed += size;
|
||||
free_count = ++DRM(mem_stats)[area].free_count;
|
||||
alloc_count = DRM(mem_stats)[area].succeed_count;
|
||||
free_count = ++DRM(mem_stats)[area].free_count;
|
||||
alloc_count = DRM(mem_stats)[area].succeed_count;
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
if (free_count > alloc_count) {
|
||||
DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
|
||||
|
@ -208,12 +207,11 @@ void DRM(free)(void *pt, size_t size, int area)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned long DRM(alloc_pages)(int order, int area)
|
||||
{
|
||||
unsigned long DRM(alloc_pages) (int order, int area) {
|
||||
unsigned long address;
|
||||
unsigned long bytes = PAGE_SIZE << order;
|
||||
unsigned long bytes = PAGE_SIZE << order;
|
||||
unsigned long addr;
|
||||
unsigned int sz;
|
||||
unsigned int sz;
|
||||
|
||||
spin_lock(&DRM(mem_lock));
|
||||
if ((DRM(ram_used) >> PAGE_SHIFT)
|
||||
|
@ -233,48 +231,44 @@ unsigned long DRM(alloc_pages)(int order, int area)
|
|||
spin_lock(&DRM(mem_lock));
|
||||
++DRM(mem_stats)[area].succeed_count;
|
||||
DRM(mem_stats)[area].bytes_allocated += bytes;
|
||||
DRM(ram_used) += bytes;
|
||||
DRM(ram_used) += bytes;
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
|
||||
|
||||
/* Zero outside the lock */
|
||||
/* Zero outside the lock */
|
||||
memset((void *)address, 0, bytes);
|
||||
|
||||
/* Reserve */
|
||||
/* Reserve */
|
||||
for (addr = address, sz = bytes;
|
||||
sz > 0;
|
||||
addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||
SetPageReserved(virt_to_page(addr));
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
void DRM(free_pages)(unsigned long address, int order, int area)
|
||||
{
|
||||
void DRM(free_pages) (unsigned long address, int order, int area) {
|
||||
unsigned long bytes = PAGE_SIZE << order;
|
||||
int alloc_count;
|
||||
int free_count;
|
||||
int alloc_count;
|
||||
int free_count;
|
||||
unsigned long addr;
|
||||
unsigned int sz;
|
||||
unsigned int sz;
|
||||
|
||||
if (!address) {
|
||||
DRM_MEM_ERROR(area, "Attempt to free address 0\n");
|
||||
} else {
|
||||
/* Unreserve */
|
||||
/* Unreserve */
|
||||
for (addr = address, sz = bytes;
|
||||
sz > 0;
|
||||
addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
|
||||
ClearPageReserved(virt_to_page(addr));
|
||||
}
|
||||
free_pages(address, order);
|
||||
}
|
||||
|
||||
spin_lock(&DRM(mem_lock));
|
||||
free_count = ++DRM(mem_stats)[area].free_count;
|
||||
alloc_count = DRM(mem_stats)[area].succeed_count;
|
||||
free_count = ++DRM(mem_stats)[area].free_count;
|
||||
alloc_count = DRM(mem_stats)[area].succeed_count;
|
||||
DRM(mem_stats)[area].bytes_freed += bytes;
|
||||
DRM(ram_used) -= bytes;
|
||||
DRM(ram_used) -= bytes;
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
if (free_count > alloc_count) {
|
||||
DRM_MEM_ERROR(area,
|
||||
|
@ -283,8 +277,8 @@ void DRM(free_pages)(unsigned long address, int order, int area)
|
|||
}
|
||||
}
|
||||
|
||||
void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
|
||||
{
|
||||
void *DRM(ioremap) (unsigned long offset, unsigned long size,
|
||||
drm_device_t * dev) {
|
||||
void *pt;
|
||||
|
||||
if (!size) {
|
||||
|
@ -306,8 +300,8 @@ void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
|
|||
return pt;
|
||||
}
|
||||
|
||||
void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev)
|
||||
{
|
||||
void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size,
|
||||
drm_device_t * dev) {
|
||||
void *pt;
|
||||
|
||||
if (!size) {
|
||||
|
@ -329,8 +323,7 @@ void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_
|
|||
return pt;
|
||||
}
|
||||
|
||||
void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
|
||||
{
|
||||
void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) {
|
||||
int alloc_count;
|
||||
int free_count;
|
||||
|
||||
|
@ -342,8 +335,8 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
|
|||
|
||||
spin_lock(&DRM(mem_lock));
|
||||
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;
|
||||
free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
|
||||
alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
|
||||
free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
|
||||
alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
if (free_count > alloc_count) {
|
||||
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
|
||||
|
@ -354,8 +347,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
|
|||
|
||||
#if __OS_HAS_AGP
|
||||
|
||||
DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
|
||||
{
|
||||
DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) {
|
||||
DRM_AGP_MEM *handle;
|
||||
|
||||
if (!pages) {
|
||||
|
@ -363,11 +355,11 @@ DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ((handle = DRM(agp_allocate_memory)(pages, type))) {
|
||||
if ((handle = DRM(agp_allocate_memory) (pages, type))) {
|
||||
spin_lock(&DRM(mem_lock));
|
||||
++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
|
||||
DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
|
||||
+= pages << PAGE_SHIFT;
|
||||
+= pages << PAGE_SHIFT;
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
return handle;
|
||||
}
|
||||
|
@ -377,11 +369,10 @@ DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int DRM(free_agp)(DRM_AGP_MEM *handle, int pages)
|
||||
{
|
||||
int alloc_count;
|
||||
int free_count;
|
||||
int retval = -EINVAL;
|
||||
int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {
|
||||
int alloc_count;
|
||||
int free_count;
|
||||
int retval = -EINVAL;
|
||||
|
||||
if (!handle) {
|
||||
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
|
||||
|
@ -389,12 +380,12 @@ int DRM(free_agp)(DRM_AGP_MEM *handle, int pages)
|
|||
return retval;
|
||||
}
|
||||
|
||||
if (DRM(agp_free_memory)(handle)) {
|
||||
if (DRM(agp_free_memory) (handle)) {
|
||||
spin_lock(&DRM(mem_lock));
|
||||
free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
|
||||
alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
|
||||
free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
|
||||
alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
|
||||
DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
|
||||
+= pages << PAGE_SHIFT;
|
||||
+= pages << PAGE_SHIFT;
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
if (free_count > alloc_count) {
|
||||
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
|
||||
|
@ -406,8 +397,7 @@ int DRM(free_agp)(DRM_AGP_MEM *handle, int pages)
|
|||
return retval;
|
||||
}
|
||||
|
||||
int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start)
|
||||
{
|
||||
int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) {
|
||||
int retcode = -EINVAL;
|
||||
|
||||
if (!handle) {
|
||||
|
@ -416,11 +406,11 @@ int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start)
|
|||
return retcode;
|
||||
}
|
||||
|
||||
if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
|
||||
if (!(retcode = DRM(agp_bind_memory) (handle, start))) {
|
||||
spin_lock(&DRM(mem_lock));
|
||||
++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
|
||||
DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
|
||||
+= handle->page_count << PAGE_SHIFT;
|
||||
+= handle->page_count << PAGE_SHIFT;
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
return retcode;
|
||||
}
|
||||
|
@ -430,8 +420,7 @@ int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start)
|
|||
return retcode;
|
||||
}
|
||||
|
||||
int DRM(unbind_agp)(DRM_AGP_MEM *handle)
|
||||
{
|
||||
int DRM(unbind_agp) (DRM_AGP_MEM * handle) {
|
||||
int alloc_count;
|
||||
int free_count;
|
||||
int retcode = -EINVAL;
|
||||
|
@ -442,12 +431,13 @@ int DRM(unbind_agp)(DRM_AGP_MEM *handle)
|
|||
return retcode;
|
||||
}
|
||||
|
||||
if ((retcode = DRM(agp_unbind_memory)(handle))) return retcode;
|
||||
if ((retcode = DRM(agp_unbind_memory) (handle)))
|
||||
return retcode;
|
||||
spin_lock(&DRM(mem_lock));
|
||||
free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
|
||||
free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
|
||||
alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
|
||||
DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
|
||||
+= handle->page_count << PAGE_SHIFT;
|
||||
+= handle->page_count << PAGE_SHIFT;
|
||||
spin_unlock(&DRM(mem_lock));
|
||||
if (free_count > alloc_count) {
|
||||
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* OS abstraction macros.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/delay.h>
|
||||
|
||||
|
@ -47,25 +46,25 @@
|
|||
#else
|
||||
/* define some dummy types for non AGP supporting kernels */
|
||||
struct no_agp_kern {
|
||||
unsigned long aper_base;
|
||||
unsigned long aper_size;
|
||||
unsigned long aper_base;
|
||||
unsigned long aper_size;
|
||||
};
|
||||
#define DRM_AGP_MEM int
|
||||
#define DRM_AGP_KERN struct no_agp_kern
|
||||
#endif
|
||||
|
||||
#if !(__OS_HAS_MTRR)
|
||||
static __inline__ int mtrr_add (unsigned long base, unsigned long size,
|
||||
unsigned int type, char increment)
|
||||
static __inline__ int mtrr_add(unsigned long base, unsigned long size,
|
||||
unsigned int type, char increment)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static __inline__ int mtrr_del (int reg, unsigned long base,
|
||||
unsigned long size)
|
||||
static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#define MTRR_TYPE_WRCOMB 1
|
||||
|
||||
#endif
|
||||
|
@ -99,7 +98,7 @@ static __inline__ int mtrr_del (int reg, unsigned long base,
|
|||
|
||||
#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
|
||||
|
||||
/**
|
||||
/**
|
||||
* Get the pointer to the SAREA.
|
||||
*
|
||||
* Searches the SAREA on the mapping lists and points drm_device::sarea to it.
|
||||
|
@ -143,7 +142,5 @@ do { \
|
|||
remove_wait_queue(&(queue), &entry); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
|
||||
#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
|
|||
dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
|
||||
if (!dmah)
|
||||
return NULL;
|
||||
|
||||
|
||||
dmah->size = size;
|
||||
dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
|
||||
|
||||
|
@ -106,6 +106,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
|
|||
|
||||
return dmah;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_pci_alloc);
|
||||
|
||||
/**
|
||||
|
@ -113,8 +114,7 @@ EXPORT_SYMBOL(drm_pci_alloc);
|
|||
*
|
||||
* This function is for internal use in the Linux-specific DRM core code.
|
||||
*/
|
||||
void
|
||||
__drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
|
||||
void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
|
||||
{
|
||||
#ifdef DRM_DEBUG_MEMORY
|
||||
int area = DRM_MEM_DMA;
|
||||
|
@ -150,12 +150,12 @@ __drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
|
|||
/**
|
||||
* \brief Free a PCI consistent memory block
|
||||
*/
|
||||
void
|
||||
drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah)
|
||||
void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
|
||||
{
|
||||
__drm_pci_free(dev, dmah);
|
||||
kfree(dmah);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_pci_free);
|
||||
|
||||
/*@}*/
|
||||
|
|
|
@ -234,4 +234,3 @@
|
|||
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
|
||||
{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
|
||||
{0, 0, 0}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_proc.h
|
||||
* \file drm_proc.c
|
||||
* /proc support for DRM
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
|
@ -39,19 +39,19 @@
|
|||
|
||||
#include "drmP.h"
|
||||
|
||||
static int drm_name_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_vm_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_clients_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_queues_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_bufs_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_name_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_vm_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_clients_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_queues_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_bufs_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
#if DRM_DEBUG_CODE
|
||||
static int drm_vma_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
static int drm_vma_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -59,18 +59,21 @@ static int drm_vma_info(char *buf, char **start, off_t offset,
|
|||
*/
|
||||
static struct drm_proc_list {
|
||||
const char *name; /**< file name */
|
||||
int (*f)(char *, char **, off_t, int, int *, void *); /**< proc callback*/
|
||||
int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/
|
||||
} drm_proc_list[] = {
|
||||
{ "name", drm_name_info },
|
||||
{ "mem", drm_mem_info },
|
||||
{ "vm", drm_vm_info },
|
||||
{ "clients", drm_clients_info },
|
||||
{ "queues", drm_queues_info },
|
||||
{ "bufs", drm_bufs_info },
|
||||
{
|
||||
"name", drm_name_info}, {
|
||||
"mem", drm_mem_info}, {
|
||||
"vm", drm_vm_info}, {
|
||||
"clients", drm_clients_info}, {
|
||||
"queues", drm_queues_info}, {
|
||||
"bufs", drm_bufs_info},
|
||||
#if DRM_DEBUG_CODE
|
||||
{ "vma", drm_vma_info },
|
||||
{
|
||||
"vma", drm_vma_info},
|
||||
#endif
|
||||
};
|
||||
|
||||
#define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
|
||||
|
||||
/**
|
||||
|
@ -81,18 +84,17 @@ static struct drm_proc_list {
|
|||
* \param root DRI proc dir entry.
|
||||
* \param dev_root resulting DRI device proc dir entry.
|
||||
* \return root entry pointer on success, or NULL on failure.
|
||||
*
|
||||
*
|
||||
* Create the DRI proc root entry "/proc/dri", the device proc root entry
|
||||
* "/proc/dri/%minor%/", and each entry in proc_list as
|
||||
* "/proc/dri/%minor%/%name%".
|
||||
*/
|
||||
int drm_proc_init(drm_device_t *dev, int minor,
|
||||
struct proc_dir_entry *root,
|
||||
struct proc_dir_entry **dev_root)
|
||||
int drm_proc_init(drm_device_t * dev, int minor,
|
||||
struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
|
||||
{
|
||||
struct proc_dir_entry *ent;
|
||||
int i, j;
|
||||
char name[64];
|
||||
int i, j;
|
||||
char name[64];
|
||||
|
||||
sprintf(name, "%d", minor);
|
||||
*dev_root = proc_mkdir(name, root);
|
||||
|
@ -103,7 +105,7 @@ int drm_proc_init(drm_device_t *dev, int minor,
|
|||
|
||||
for (i = 0; i < DRM_PROC_ENTRIES; i++) {
|
||||
ent = create_proc_entry(drm_proc_list[i].name,
|
||||
S_IFREG|S_IRUGO, *dev_root);
|
||||
S_IFREG | S_IRUGO, *dev_root);
|
||||
if (!ent) {
|
||||
DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
|
||||
name, drm_proc_list[i].name);
|
||||
|
@ -114,13 +116,12 @@ int drm_proc_init(drm_device_t *dev, int minor,
|
|||
return -1;
|
||||
}
|
||||
ent->read_proc = drm_proc_list[i].f;
|
||||
ent->data = dev;
|
||||
ent->data = dev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup the proc filesystem resources.
|
||||
*
|
||||
|
@ -132,12 +133,13 @@ int drm_proc_init(drm_device_t *dev, int minor,
|
|||
* Remove all proc entries created by proc_init().
|
||||
*/
|
||||
int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
|
||||
struct proc_dir_entry *dev_root)
|
||||
struct proc_dir_entry *dev_root)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
char name[64];
|
||||
|
||||
if (!root || !dev_root) return 0;
|
||||
if (!root || !dev_root)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < DRM_PROC_ENTRIES; i++)
|
||||
remove_proc_entry(drm_proc_list[i].name, dev_root);
|
||||
|
@ -149,7 +151,7 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
|
|||
|
||||
/**
|
||||
* Called when "/proc/dri/.../name" is read.
|
||||
*
|
||||
*
|
||||
* \param buf output buffer.
|
||||
* \param start start of output data.
|
||||
* \param offset requested start offset.
|
||||
|
@ -157,14 +159,14 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
|
|||
* \param eof whether there is no more data to return.
|
||||
* \param data private data.
|
||||
* \return number of written bytes.
|
||||
*
|
||||
*
|
||||
* Prints the device name together with the bus id if available.
|
||||
*/
|
||||
static int drm_name_info(char *buf, char **start, off_t offset, int request,
|
||||
int *eof, void *data)
|
||||
int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int len = 0;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int len = 0;
|
||||
|
||||
if (offset > DRM_PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
|
@ -172,23 +174,26 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
|
|||
}
|
||||
|
||||
*start = &buf[offset];
|
||||
*eof = 0;
|
||||
*eof = 0;
|
||||
|
||||
if (dev->unique) {
|
||||
DRM_PROC_PRINT("%s %s %s\n",
|
||||
dev->driver->pci_driver.name, pci_name(dev->pdev), dev->unique);
|
||||
dev->driver->pci_driver.name,
|
||||
pci_name(dev->pdev), dev->unique);
|
||||
} else {
|
||||
DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, pci_name(dev->pdev));
|
||||
DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
|
||||
pci_name(dev->pdev));
|
||||
}
|
||||
|
||||
if (len > request + offset) return request;
|
||||
if (len > request + offset)
|
||||
return request;
|
||||
*eof = 1;
|
||||
return len - offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when "/proc/dri/.../vm" is read.
|
||||
*
|
||||
*
|
||||
* \param buf output buffer.
|
||||
* \param start start of output data.
|
||||
* \param offset requested start offset.
|
||||
|
@ -196,24 +201,24 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
|
|||
* \param eof whether there is no more data to return.
|
||||
* \param data private data.
|
||||
* \return number of written bytes.
|
||||
*
|
||||
*
|
||||
* Prints information about all mappings in drm_device::maplist.
|
||||
*/
|
||||
static int drm__vm_info(char *buf, char **start, off_t offset, int request,
|
||||
int *eof, void *data)
|
||||
int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int len = 0;
|
||||
drm_map_t *map;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int len = 0;
|
||||
drm_map_t *map;
|
||||
drm_map_list_t *r_list;
|
||||
struct list_head *list;
|
||||
|
||||
/* Hardcoded from _DRM_FRAME_BUFFER,
|
||||
_DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
|
||||
_DRM_SCATTER_GATHER and _DRM_CONSISTENT */
|
||||
const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
|
||||
const char *type;
|
||||
int i;
|
||||
/* Hardcoded from _DRM_FRAME_BUFFER,
|
||||
_DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
|
||||
_DRM_SCATTER_GATHER and _DRM_CONSISTENT */
|
||||
const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
|
||||
const char *type;
|
||||
int i;
|
||||
|
||||
if (offset > DRM_PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
|
@ -221,36 +226,35 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
|
|||
}
|
||||
|
||||
*start = &buf[offset];
|
||||
*eof = 0;
|
||||
*eof = 0;
|
||||
|
||||
DRM_PROC_PRINT("slot offset size type flags "
|
||||
"address mtrr\n\n");
|
||||
i = 0;
|
||||
if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
|
||||
if (dev->maplist != NULL)
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
map = r_list->map;
|
||||
if(!map)
|
||||
if (!map)
|
||||
continue;
|
||||
if (map->type < 0 || map->type > 5)
|
||||
type = "??";
|
||||
else
|
||||
else
|
||||
type = types[map->type];
|
||||
DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08x ",
|
||||
i,
|
||||
map->offset,
|
||||
map->size,
|
||||
type,
|
||||
map->flags,
|
||||
r_list->user_token);
|
||||
map->size, type, map->flags, r_list->user_token);
|
||||
if (map->mtrr < 0) {
|
||||
DRM_PROC_PRINT("none\n");
|
||||
} else {
|
||||
DRM_PROC_PRINT("%4d\n", map->mtrr);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > request + offset) return request;
|
||||
if (len > request + offset)
|
||||
return request;
|
||||
*eof = 1;
|
||||
return len - offset;
|
||||
}
|
||||
|
@ -259,10 +263,10 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
|
|||
* Simply calls _vm_info() while holding the drm_device::struct_sem lock.
|
||||
*/
|
||||
static int drm_vm_info(char *buf, char **start, off_t offset, int request,
|
||||
int *eof, void *data)
|
||||
int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int ret;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int ret;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
ret = drm__vm_info(buf, start, offset, request, eof, data);
|
||||
|
@ -272,7 +276,7 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
|
|||
|
||||
/**
|
||||
* Called when "/proc/dri/.../queues" is read.
|
||||
*
|
||||
*
|
||||
* \param buf output buffer.
|
||||
* \param start start of output data.
|
||||
* \param offset requested start offset.
|
||||
|
@ -282,12 +286,12 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
|
|||
* \return number of written bytes.
|
||||
*/
|
||||
static int drm__queues_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data)
|
||||
int request, int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int len = 0;
|
||||
int i;
|
||||
drm_queue_t *q;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int len = 0;
|
||||
int i;
|
||||
drm_queue_t *q;
|
||||
|
||||
if (offset > DRM_PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
|
@ -295,7 +299,7 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
|
|||
}
|
||||
|
||||
*start = &buf[offset];
|
||||
*eof = 0;
|
||||
*eof = 0;
|
||||
|
||||
DRM_PROC_PRINT(" ctx/flags use fin"
|
||||
" blk/rw/rwf wait flushed queued"
|
||||
|
@ -313,14 +317,17 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
|
|||
atomic_read(&q->block_count),
|
||||
atomic_read(&q->block_read) ? 'r' : '-',
|
||||
atomic_read(&q->block_write) ? 'w' : '-',
|
||||
waitqueue_active(&q->read_queue) ? 'r':'-',
|
||||
waitqueue_active(&q->write_queue) ? 'w':'-',
|
||||
waitqueue_active(&q->flush_queue) ? 'f':'-',
|
||||
waitqueue_active(&q->read_queue) ? 'r' : '-',
|
||||
waitqueue_active(&q->
|
||||
write_queue) ? 'w' : '-',
|
||||
waitqueue_active(&q->
|
||||
flush_queue) ? 'f' : '-',
|
||||
DRM_BUFCOUNT(&q->waitlist));
|
||||
atomic_dec(&q->use_count);
|
||||
}
|
||||
|
||||
if (len > request + offset) return request;
|
||||
if (len > request + offset)
|
||||
return request;
|
||||
*eof = 1;
|
||||
return len - offset;
|
||||
}
|
||||
|
@ -329,10 +336,10 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
|
|||
* Simply calls _queues_info() while holding the drm_device::struct_sem lock.
|
||||
*/
|
||||
static int drm_queues_info(char *buf, char **start, off_t offset, int request,
|
||||
int *eof, void *data)
|
||||
int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int ret;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int ret;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
ret = drm__queues_info(buf, start, offset, request, eof, data);
|
||||
|
@ -342,7 +349,7 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
|
|||
|
||||
/**
|
||||
* Called when "/proc/dri/.../bufs" is read.
|
||||
*
|
||||
*
|
||||
* \param buf output buffer.
|
||||
* \param start start of output data.
|
||||
* \param offset requested start offset.
|
||||
|
@ -352,12 +359,12 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
|
|||
* \return number of written bytes.
|
||||
*/
|
||||
static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
|
||||
int *eof, void *data)
|
||||
int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int len = 0;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int len = 0;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (!dma || offset > DRM_PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
|
@ -365,7 +372,7 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
|
|||
}
|
||||
|
||||
*start = &buf[offset];
|
||||
*eof = 0;
|
||||
*eof = 0;
|
||||
|
||||
DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
|
@ -378,19 +385,21 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
|
|||
.freelist.count),
|
||||
dma->bufs[i].seg_count,
|
||||
dma->bufs[i].seg_count
|
||||
*(1 << dma->bufs[i].page_order),
|
||||
* (1 << dma->bufs[i].page_order),
|
||||
(dma->bufs[i].seg_count
|
||||
* (1 << dma->bufs[i].page_order))
|
||||
* PAGE_SIZE / 1024);
|
||||
}
|
||||
DRM_PROC_PRINT("\n");
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (i && !(i%32)) DRM_PROC_PRINT("\n");
|
||||
if (i && !(i % 32))
|
||||
DRM_PROC_PRINT("\n");
|
||||
DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
|
||||
}
|
||||
DRM_PROC_PRINT("\n");
|
||||
|
||||
if (len > request + offset) return request;
|
||||
if (len > request + offset)
|
||||
return request;
|
||||
*eof = 1;
|
||||
return len - offset;
|
||||
}
|
||||
|
@ -399,10 +408,10 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
|
|||
* Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
|
||||
*/
|
||||
static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
|
||||
int *eof, void *data)
|
||||
int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int ret;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int ret;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
ret = drm__bufs_info(buf, start, offset, request, eof, data);
|
||||
|
@ -412,7 +421,7 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
|
|||
|
||||
/**
|
||||
* Called when "/proc/dri/.../clients" is read.
|
||||
*
|
||||
*
|
||||
* \param buf output buffer.
|
||||
* \param start start of output data.
|
||||
* \param offset requested start offset.
|
||||
|
@ -422,11 +431,11 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
|
|||
* \return number of written bytes.
|
||||
*/
|
||||
static int drm__clients_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data)
|
||||
int request, int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int len = 0;
|
||||
drm_file_t *priv;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int len = 0;
|
||||
drm_file_t *priv;
|
||||
|
||||
if (offset > DRM_PROC_LIMIT) {
|
||||
*eof = 1;
|
||||
|
@ -434,7 +443,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
|
|||
}
|
||||
|
||||
*start = &buf[offset];
|
||||
*eof = 0;
|
||||
*eof = 0;
|
||||
|
||||
DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
|
||||
for (priv = dev->file_first; priv; priv = priv->next) {
|
||||
|
@ -442,12 +451,11 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
|
|||
priv->authenticated ? 'y' : 'n',
|
||||
priv->minor,
|
||||
priv->pid,
|
||||
priv->uid,
|
||||
priv->magic,
|
||||
priv->ioctl_count);
|
||||
priv->uid, priv->magic, priv->ioctl_count);
|
||||
}
|
||||
|
||||
if (len > request + offset) return request;
|
||||
if (len > request + offset)
|
||||
return request;
|
||||
*eof = 1;
|
||||
return len - offset;
|
||||
}
|
||||
|
@ -456,10 +464,10 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
|
|||
* Simply calls _clients_info() while holding the drm_device::struct_sem lock.
|
||||
*/
|
||||
static int drm_clients_info(char *buf, char **start, off_t offset,
|
||||
int request, int *eof, void *data)
|
||||
int request, int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int ret;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int ret;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
ret = drm__clients_info(buf, start, offset, request, eof, data);
|
||||
|
@ -470,14 +478,14 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
|
|||
#if DRM_DEBUG_CODE
|
||||
|
||||
static int drm__vma_info(char *buf, char **start, off_t offset, int request,
|
||||
int *eof, void *data)
|
||||
int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int len = 0;
|
||||
drm_vma_entry_t *pt;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int len = 0;
|
||||
drm_vma_entry_t *pt;
|
||||
struct vm_area_struct *vma;
|
||||
#if defined(__i386__)
|
||||
unsigned int pgprot;
|
||||
unsigned int pgprot;
|
||||
#endif
|
||||
|
||||
if (offset > DRM_PROC_LIMIT) {
|
||||
|
@ -486,51 +494,53 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
|
|||
}
|
||||
|
||||
*start = &buf[offset];
|
||||
*eof = 0;
|
||||
*eof = 0;
|
||||
|
||||
DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
|
||||
atomic_read(&dev->vma_count),
|
||||
high_memory, virt_to_phys(high_memory));
|
||||
for (pt = dev->vmalist; pt; pt = pt->next) {
|
||||
if (!(vma = pt->vma)) continue;
|
||||
if (!(vma = pt->vma))
|
||||
continue;
|
||||
DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
|
||||
pt->pid,
|
||||
vma->vm_start,
|
||||
vma->vm_end,
|
||||
vma->vm_flags & VM_READ ? 'r' : '-',
|
||||
vma->vm_flags & VM_WRITE ? 'w' : '-',
|
||||
vma->vm_flags & VM_EXEC ? 'x' : '-',
|
||||
vma->vm_flags & VM_READ ? 'r' : '-',
|
||||
vma->vm_flags & VM_WRITE ? 'w' : '-',
|
||||
vma->vm_flags & VM_EXEC ? 'x' : '-',
|
||||
vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
|
||||
vma->vm_flags & VM_LOCKED ? 'l' : '-',
|
||||
vma->vm_flags & VM_IO ? 'i' : '-',
|
||||
vma->vm_flags & VM_LOCKED ? 'l' : '-',
|
||||
vma->vm_flags & VM_IO ? 'i' : '-',
|
||||
VM_OFFSET(vma));
|
||||
|
||||
#if defined(__i386__)
|
||||
pgprot = pgprot_val(vma->vm_page_prot);
|
||||
DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
|
||||
pgprot & _PAGE_PRESENT ? 'p' : '-',
|
||||
pgprot & _PAGE_RW ? 'w' : 'r',
|
||||
pgprot & _PAGE_USER ? 'u' : 's',
|
||||
pgprot & _PAGE_PWT ? 't' : 'b',
|
||||
pgprot & _PAGE_PCD ? 'u' : 'c',
|
||||
pgprot & _PAGE_PRESENT ? 'p' : '-',
|
||||
pgprot & _PAGE_RW ? 'w' : 'r',
|
||||
pgprot & _PAGE_USER ? 'u' : 's',
|
||||
pgprot & _PAGE_PWT ? 't' : 'b',
|
||||
pgprot & _PAGE_PCD ? 'u' : 'c',
|
||||
pgprot & _PAGE_ACCESSED ? 'a' : '-',
|
||||
pgprot & _PAGE_DIRTY ? 'd' : '-',
|
||||
pgprot & _PAGE_PSE ? 'm' : 'k',
|
||||
pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
|
||||
pgprot & _PAGE_DIRTY ? 'd' : '-',
|
||||
pgprot & _PAGE_PSE ? 'm' : 'k',
|
||||
pgprot & _PAGE_GLOBAL ? 'g' : 'l');
|
||||
#endif
|
||||
DRM_PROC_PRINT("\n");
|
||||
}
|
||||
|
||||
if (len > request + offset) return request;
|
||||
if (len > request + offset)
|
||||
return request;
|
||||
*eof = 1;
|
||||
return len - offset;
|
||||
}
|
||||
|
||||
static int drm_vma_info(char *buf, char **start, off_t offset, int request,
|
||||
int *eof, void *data)
|
||||
int *eof, void *data)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)data;
|
||||
int ret;
|
||||
drm_device_t *dev = (drm_device_t *) data;
|
||||
int ret;
|
||||
|
||||
down(&dev->struct_sem);
|
||||
ret = drm__vma_info(buf, start, offset, request, eof, data);
|
||||
|
@ -538,5 +548,3 @@ static int drm_vma_info(char *buf, char **start, off_t offset, int request,
|
|||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_sarea.h
|
||||
* \file drm_sarea.h
|
||||
* \brief SAREA definitions
|
||||
*
|
||||
* \author Michel Dänzer <michel@daenzer.net>
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if defined(__alpha__)
|
||||
#define SAREA_MAX 0x2000
|
||||
#elif defined(__ia64__)
|
||||
#define SAREA_MAX 0x10000 /* 64kB */
|
||||
#define SAREA_MAX 0x10000 /* 64kB */
|
||||
#else
|
||||
/* Intel 830M driver needs at least 8k SAREA */
|
||||
#define SAREA_MAX 0x2000
|
||||
|
@ -51,28 +51,28 @@
|
|||
|
||||
/** SAREA drawable */
|
||||
typedef struct drm_sarea_drawable {
|
||||
unsigned int stamp;
|
||||
unsigned int flags;
|
||||
unsigned int stamp;
|
||||
unsigned int flags;
|
||||
} drm_sarea_drawable_t;
|
||||
|
||||
/** SAREA frame */
|
||||
typedef struct drm_sarea_frame {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int fullscreen;
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int fullscreen;
|
||||
} drm_sarea_frame_t;
|
||||
|
||||
/** SAREA */
|
||||
typedef struct drm_sarea {
|
||||
/** first thing is always the DRM locking structure */
|
||||
drm_hw_lock_t lock;
|
||||
drm_hw_lock_t lock;
|
||||
/** \todo Use readers/writer lock for drm_sarea::drawable_lock */
|
||||
drm_hw_lock_t drawable_lock;
|
||||
drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
|
||||
drm_sarea_frame_t frame; /**< frame */
|
||||
drm_context_t dummy_context;
|
||||
drm_hw_lock_t drawable_lock;
|
||||
drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
|
||||
drm_sarea_frame_t frame; /**< frame */
|
||||
drm_context_t dummy_context;
|
||||
} drm_sarea_t;
|
||||
|
||||
#endif /* _DRM_SAREA_H_ */
|
||||
#endif /* _DRM_SAREA_H_ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* \file drm_scatter.h
|
||||
* \file drm_scatter.c
|
||||
* IOCTLs to manage scatter/gather memory
|
||||
*
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
|
@ -37,28 +37,24 @@
|
|||
|
||||
#define DEBUG_SCATTER 0
|
||||
|
||||
void drm_sg_cleanup( drm_sg_mem_t *entry )
|
||||
void drm_sg_cleanup(drm_sg_mem_t * entry)
|
||||
{
|
||||
struct page *page;
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < entry->pages ; i++ ) {
|
||||
for (i = 0; i < entry->pages; i++) {
|
||||
page = entry->pagelist[i];
|
||||
if ( page )
|
||||
ClearPageReserved( page );
|
||||
if (page)
|
||||
ClearPageReserved(page);
|
||||
}
|
||||
|
||||
vfree( entry->virtual );
|
||||
vfree(entry->virtual);
|
||||
|
||||
drm_free( entry->busaddr,
|
||||
entry->pages * sizeof(*entry->busaddr),
|
||||
DRM_MEM_PAGES );
|
||||
drm_free( entry->pagelist,
|
||||
entry->pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
drm_free( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
drm_free(entry->busaddr,
|
||||
entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
|
||||
drm_free(entry->pagelist,
|
||||
entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES);
|
||||
drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
|
||||
}
|
||||
|
||||
#ifdef _LP64
|
||||
|
@ -67,8 +63,8 @@ void drm_sg_cleanup( drm_sg_mem_t *entry )
|
|||
# define ScatterHandle(x) (unsigned int)(x)
|
||||
#endif
|
||||
|
||||
int drm_sg_alloc( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_sg_alloc(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
@ -77,75 +73,70 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
|
|||
drm_sg_mem_t *entry;
|
||||
unsigned long pages, i, j;
|
||||
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_SG))
|
||||
return -EINVAL;
|
||||
|
||||
if ( dev->sg )
|
||||
if (dev->sg)
|
||||
return -EINVAL;
|
||||
|
||||
if ( copy_from_user( &request, argp, sizeof(request) ) )
|
||||
if (copy_from_user(&request, argp, sizeof(request)))
|
||||
return -EFAULT;
|
||||
|
||||
entry = drm_alloc( sizeof(*entry), DRM_MEM_SGLISTS );
|
||||
if ( !entry )
|
||||
entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
memset( entry, 0, sizeof(*entry) );
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
|
||||
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
|
||||
DRM_DEBUG("sg size=%ld pages=%ld\n", request.size, pages);
|
||||
|
||||
entry->pages = pages;
|
||||
entry->pagelist = drm_alloc( pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
if ( !entry->pagelist ) {
|
||||
drm_free( entry, sizeof(*entry), DRM_MEM_SGLISTS );
|
||||
entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
if (!entry->pagelist) {
|
||||
drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
|
||||
|
||||
entry->busaddr = drm_alloc( pages * sizeof(*entry->busaddr),
|
||||
DRM_MEM_PAGES );
|
||||
if ( !entry->busaddr ) {
|
||||
drm_free( entry->pagelist,
|
||||
entry->pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
drm_free( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
entry->busaddr = drm_alloc(pages * sizeof(*entry->busaddr),
|
||||
DRM_MEM_PAGES);
|
||||
if (!entry->busaddr) {
|
||||
drm_free(entry->pagelist,
|
||||
entry->pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
|
||||
memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
|
||||
|
||||
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
|
||||
if ( !entry->virtual ) {
|
||||
drm_free( entry->busaddr,
|
||||
entry->pages * sizeof(*entry->busaddr),
|
||||
DRM_MEM_PAGES );
|
||||
drm_free( entry->pagelist,
|
||||
entry->pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES );
|
||||
drm_free( entry,
|
||||
sizeof(*entry),
|
||||
DRM_MEM_SGLISTS );
|
||||
entry->virtual = vmalloc_32(pages << PAGE_SHIFT);
|
||||
if (!entry->virtual) {
|
||||
drm_free(entry->busaddr,
|
||||
entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
|
||||
drm_free(entry->pagelist,
|
||||
entry->pages * sizeof(*entry->pagelist),
|
||||
DRM_MEM_PAGES);
|
||||
drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* This also forces the mapping of COW pages, so our page list
|
||||
* will be valid. Please don't remove it...
|
||||
*/
|
||||
memset( entry->virtual, 0, pages << PAGE_SHIFT );
|
||||
memset(entry->virtual, 0, pages << PAGE_SHIFT);
|
||||
|
||||
entry->handle = ScatterHandle((unsigned long)entry->virtual);
|
||||
|
||||
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
|
||||
DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
|
||||
DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
|
||||
DRM_DEBUG("sg alloc virtual = %p\n", entry->virtual);
|
||||
|
||||
for (i = (unsigned long)entry->virtual, j = 0; j < pages;
|
||||
i += PAGE_SIZE, j++) {
|
||||
for (i = (unsigned long)entry->virtual, j = 0; j < pages;
|
||||
i += PAGE_SIZE, j++) {
|
||||
entry->pagelist[j] = vmalloc_to_page((void *)i);
|
||||
if (!entry->pagelist[j])
|
||||
goto failed;
|
||||
|
@ -154,8 +145,8 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
|
|||
|
||||
request.handle = entry->handle;
|
||||
|
||||
if ( copy_to_user( argp, &request, sizeof(request) ) ) {
|
||||
drm_sg_cleanup( entry );
|
||||
if (copy_to_user(argp, &request, sizeof(request))) {
|
||||
drm_sg_cleanup(entry);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -166,50 +157,50 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
|
|||
* versa.
|
||||
*/
|
||||
{
|
||||
int error = 0;
|
||||
int error = 0;
|
||||
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
unsigned long *tmp;
|
||||
for (i = 0; i < pages; i++) {
|
||||
unsigned long *tmp;
|
||||
|
||||
tmp = page_address( entry->pagelist[i] );
|
||||
for ( j = 0 ;
|
||||
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||
j++, tmp++ ) {
|
||||
*tmp = 0xcafebabe;
|
||||
}
|
||||
tmp = (unsigned long *)((u8 *)entry->virtual +
|
||||
(PAGE_SIZE * i));
|
||||
for( j = 0 ;
|
||||
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||
j++, tmp++ ) {
|
||||
if ( *tmp != 0xcafebabe && error == 0 ) {
|
||||
error = 1;
|
||||
DRM_ERROR( "Scatter allocation error, "
|
||||
"pagelist does not match "
|
||||
"virtual mapping\n" );
|
||||
tmp = page_address(entry->pagelist[i]);
|
||||
for (j = 0;
|
||||
j < PAGE_SIZE / sizeof(unsigned long);
|
||||
j++, tmp++) {
|
||||
*tmp = 0xcafebabe;
|
||||
}
|
||||
tmp = (unsigned long *)((u8 *) entry->virtual +
|
||||
(PAGE_SIZE * i));
|
||||
for (j = 0;
|
||||
j < PAGE_SIZE / sizeof(unsigned long);
|
||||
j++, tmp++) {
|
||||
if (*tmp != 0xcafebabe && error == 0) {
|
||||
error = 1;
|
||||
DRM_ERROR("Scatter allocation error, "
|
||||
"pagelist does not match "
|
||||
"virtual mapping\n");
|
||||
}
|
||||
}
|
||||
tmp = page_address(entry->pagelist[i]);
|
||||
for (j = 0;
|
||||
j < PAGE_SIZE / sizeof(unsigned long);
|
||||
j++, tmp++) {
|
||||
*tmp = 0;
|
||||
}
|
||||
}
|
||||
tmp = page_address( entry->pagelist[i] );
|
||||
for(j = 0 ;
|
||||
j < PAGE_SIZE / sizeof(unsigned long) ;
|
||||
j++, tmp++) {
|
||||
*tmp = 0;
|
||||
}
|
||||
}
|
||||
if (error == 0)
|
||||
DRM_ERROR( "Scatter allocation matches pagelist\n" );
|
||||
if (error == 0)
|
||||
DRM_ERROR("Scatter allocation matches pagelist\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
drm_sg_cleanup( entry );
|
||||
failed:
|
||||
drm_sg_cleanup(entry);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int drm_sg_free( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg )
|
||||
int drm_sg_free(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
@ -219,20 +210,20 @@ int drm_sg_free( struct inode *inode, struct file *filp,
|
|||
if (!drm_core_check_feature(dev, DRIVER_SG))
|
||||
return -EINVAL;
|
||||
|
||||
if ( copy_from_user( &request,
|
||||
(drm_scatter_gather_t __user *)arg,
|
||||
sizeof(request) ) )
|
||||
if (copy_from_user(&request,
|
||||
(drm_scatter_gather_t __user *) arg,
|
||||
sizeof(request)))
|
||||
return -EFAULT;
|
||||
|
||||
entry = dev->sg;
|
||||
dev->sg = NULL;
|
||||
|
||||
if ( !entry || entry->handle != request.handle )
|
||||
if (!entry || entry->handle != request.handle)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
|
||||
DRM_DEBUG("sg free virtual = %p\n", entry->virtual);
|
||||
|
||||
drm_sg_cleanup( entry );
|
||||
drm_sg_cleanup(entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -37,11 +37,11 @@
|
|||
#include "drm_core.h"
|
||||
|
||||
unsigned int drm_cards_limit = 16; /* Enough for one machine */
|
||||
unsigned int drm_debug = 0; /* 1 to enable debug output */
|
||||
unsigned int drm_debug = 0; /* 1 to enable debug output */
|
||||
EXPORT_SYMBOL(drm_debug);
|
||||
|
||||
MODULE_AUTHOR( CORE_AUTHOR );
|
||||
MODULE_DESCRIPTION( CORE_DESC );
|
||||
MODULE_AUTHOR(CORE_AUTHOR);
|
||||
MODULE_DESCRIPTION(CORE_DESC);
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
|
||||
MODULE_PARM_DESC(debug, "Enable debug output");
|
||||
|
@ -53,19 +53,21 @@ drm_head_t **drm_heads;
|
|||
struct drm_sysfs_class *drm_class;
|
||||
struct proc_dir_entry *drm_proc_root;
|
||||
|
||||
static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver)
|
||||
static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
spin_lock_init(&dev->count_lock);
|
||||
init_timer( &dev->timer );
|
||||
sema_init( &dev->struct_sem, 1 );
|
||||
sema_init( &dev->ctxlist_sem, 1 );
|
||||
init_timer(&dev->timer);
|
||||
sema_init(&dev->struct_sem, 1);
|
||||
sema_init(&dev->ctxlist_sem, 1);
|
||||
|
||||
dev->pdev = pdev;
|
||||
dev->pdev = pdev;
|
||||
|
||||
#ifdef __alpha__
|
||||
dev->hose = pdev->sysdata;
|
||||
dev->hose = pdev->sysdata;
|
||||
dev->pci_domain = dev->hose->bus->number;
|
||||
#else
|
||||
dev->pci_domain = 0;
|
||||
|
@ -82,15 +84,15 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
|
|||
|
||||
/* the DRM has 6 basic counters */
|
||||
dev->counters = 6;
|
||||
dev->types[0] = _DRM_STAT_LOCK;
|
||||
dev->types[1] = _DRM_STAT_OPENS;
|
||||
dev->types[2] = _DRM_STAT_CLOSES;
|
||||
dev->types[3] = _DRM_STAT_IOCTLS;
|
||||
dev->types[4] = _DRM_STAT_LOCKS;
|
||||
dev->types[5] = _DRM_STAT_UNLOCKS;
|
||||
dev->types[0] = _DRM_STAT_LOCK;
|
||||
dev->types[1] = _DRM_STAT_OPENS;
|
||||
dev->types[2] = _DRM_STAT_CLOSES;
|
||||
dev->types[3] = _DRM_STAT_IOCTLS;
|
||||
dev->types[4] = _DRM_STAT_LOCKS;
|
||||
dev->types[5] = _DRM_STAT_UNLOCKS;
|
||||
|
||||
dev->driver = driver;
|
||||
|
||||
|
||||
if (dev->driver->preinit)
|
||||
if ((retcode = dev->driver->preinit(dev, ent->driver_data)))
|
||||
goto error_out_unreg;
|
||||
|
@ -98,29 +100,30 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
|
|||
if (drm_core_has_AGP(dev)) {
|
||||
if (drm_device_is_agp(dev))
|
||||
dev->agp = drm_agp_init(dev);
|
||||
if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
|
||||
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
|
||||
if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
|
||||
&& (dev->agp == NULL)) {
|
||||
DRM_ERROR("Cannot initialize the agpgart module.\n");
|
||||
retcode = -EINVAL;
|
||||
goto error_out_unreg;
|
||||
}
|
||||
if (drm_core_has_MTRR(dev)) {
|
||||
if (dev->agp)
|
||||
dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size*1024*1024,
|
||||
MTRR_TYPE_WRCOMB,
|
||||
1 );
|
||||
dev->agp->agp_mtrr =
|
||||
mtrr_add(dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size *
|
||||
1024 * 1024, MTRR_TYPE_WRCOMB, 1);
|
||||
}
|
||||
}
|
||||
|
||||
retcode = drm_ctxbitmap_init( dev );
|
||||
if( retcode ) {
|
||||
DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
|
||||
retcode = drm_ctxbitmap_init(dev);
|
||||
if (retcode) {
|
||||
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
|
||||
goto error_out_unreg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_out_unreg:
|
||||
|
||||
error_out_unreg:
|
||||
drm_takedown(dev);
|
||||
return retcode;
|
||||
}
|
||||
|
@ -140,7 +143,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
|
|||
int minor = iminor(inode);
|
||||
int err = -ENODEV;
|
||||
struct file_operations *old_fops;
|
||||
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!((minor >= 0) && (minor < drm_cards_limit)))
|
||||
|
@ -148,7 +151,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
|
|||
|
||||
if (!drm_heads[minor])
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
if (!(dev = drm_heads[minor]->dev))
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -174,7 +177,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
|
|||
* create the proc init entry via proc_init(). This routines assigns
|
||||
* minor numbers to secondary heads of multi-headed cards
|
||||
*/
|
||||
static int drm_get_head(drm_device_t *dev, drm_head_t *head)
|
||||
static int drm_get_head(drm_device_t * dev, drm_head_t * head)
|
||||
{
|
||||
drm_head_t **heads = drm_heads;
|
||||
int ret;
|
||||
|
@ -184,26 +187,27 @@ static int drm_get_head(drm_device_t *dev, drm_head_t *head)
|
|||
|
||||
for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
|
||||
if (!*heads) {
|
||||
|
||||
|
||||
*head = (drm_head_t) {
|
||||
.dev = dev,
|
||||
.device = MKDEV(DRM_MAJOR, minor),
|
||||
.minor = minor,
|
||||
};
|
||||
|
||||
if ((ret = drm_proc_init(dev, minor, drm_proc_root, &head->dev_root))) {
|
||||
printk (KERN_ERR "DRM: Failed to initialize /proc/dri.\n");
|
||||
.dev = dev,.device =
|
||||
MKDEV(DRM_MAJOR, minor),.minor = minor,};
|
||||
|
||||
if ((ret =
|
||||
drm_proc_init(dev, minor, drm_proc_root,
|
||||
&head->dev_root))) {
|
||||
printk(KERN_ERR
|
||||
"DRM: Failed to initialize /proc/dri.\n");
|
||||
goto err_g1;
|
||||
}
|
||||
|
||||
|
||||
head->dev_class = drm_sysfs_device_add(drm_class,
|
||||
MKDEV(DRM_MAJOR,
|
||||
minor),
|
||||
&dev->pdev->dev,
|
||||
"card%d", minor);
|
||||
if (IS_ERR(head->dev_class)) {
|
||||
printk(KERN_ERR "DRM: Error sysfs_device_add.\n");
|
||||
printk(KERN_ERR
|
||||
"DRM: Error sysfs_device_add.\n");
|
||||
ret = PTR_ERR(head->dev_class);
|
||||
goto err_g2;
|
||||
}
|
||||
|
@ -215,13 +219,14 @@ static int drm_get_head(drm_device_t *dev, drm_head_t *head)
|
|||
}
|
||||
DRM_ERROR("out of minors\n");
|
||||
return -ENOMEM;
|
||||
err_g2:
|
||||
err_g2:
|
||||
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
|
||||
err_g1:
|
||||
*head = (drm_head_t) {.dev = NULL};
|
||||
err_g1:
|
||||
*head = (drm_head_t) {
|
||||
.dev = NULL};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
|
@ -234,7 +239,7 @@ err_g1:
|
|||
* Try and register, if we fail to register, backout previous work.
|
||||
*/
|
||||
int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
drm_device_t *dev;
|
||||
int ret;
|
||||
|
@ -261,10 +266,11 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
|||
|
||||
return 0;
|
||||
|
||||
err_g1:
|
||||
err_g1:
|
||||
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_get_dev);
|
||||
|
||||
/**
|
||||
|
@ -305,19 +311,19 @@ int drm_put_dev(drm_device_t * dev)
|
|||
* last minor released.
|
||||
*
|
||||
*/
|
||||
int drm_put_head(drm_head_t *head)
|
||||
int drm_put_head(drm_head_t * head)
|
||||
{
|
||||
int minor = head->minor;
|
||||
|
||||
|
||||
DRM_DEBUG("release secondary minor %d\n", minor);
|
||||
|
||||
|
||||
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
|
||||
drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor));
|
||||
|
||||
*head = (drm_head_t){.dev = NULL};
|
||||
|
||||
*head = (drm_head_t) {
|
||||
.dev = NULL};
|
||||
|
||||
drm_heads[minor] = NULL;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* \file drm_vm.h
|
||||
* \file drm_vm.c
|
||||
* Memory mapping for DRM
|
||||
*
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
@ -47,32 +47,34 @@ static void drm_vm_close(struct vm_area_struct *vma);
|
|||
* \param vma virtual memory area.
|
||||
* \param address access address.
|
||||
* \return pointer to the page structure.
|
||||
*
|
||||
*
|
||||
* Find the right map and if it's AGP memory find the real physical page to
|
||||
* map, get the page, increment the use count and return it.
|
||||
*/
|
||||
#if __OS_HAS_AGP
|
||||
static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address)
|
||||
unsigned long address)
|
||||
{
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_map_t *map = NULL;
|
||||
drm_map_list_t *r_list;
|
||||
drm_map_t *map = NULL;
|
||||
drm_map_list_t *r_list;
|
||||
struct list_head *list;
|
||||
|
||||
/*
|
||||
* Find the right map
|
||||
*/
|
||||
* Find the right map
|
||||
*/
|
||||
if (!drm_core_has_AGP(dev))
|
||||
goto vm_nopage_error;
|
||||
|
||||
if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error;
|
||||
if (!dev->agp || !dev->agp->cant_use_aperture)
|
||||
goto vm_nopage_error;
|
||||
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
map = r_list->map;
|
||||
if (!map) continue;
|
||||
if (!map)
|
||||
continue;
|
||||
if (r_list->user_token == VM_OFFSET(vma))
|
||||
break;
|
||||
}
|
||||
|
@ -85,45 +87,47 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
|
|||
|
||||
#ifdef __alpha__
|
||||
/*
|
||||
* Adjust to a bus-relative address
|
||||
*/
|
||||
* Adjust to a bus-relative address
|
||||
*/
|
||||
baddr -= dev->hose->mem_space->start;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* It's AGP memory - find the real physical page to map
|
||||
*/
|
||||
for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
|
||||
* It's AGP memory - find the real physical page to map
|
||||
*/
|
||||
for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
|
||||
if (agpmem->bound <= baddr &&
|
||||
agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
|
||||
agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!agpmem) goto vm_nopage_error;
|
||||
if (!agpmem)
|
||||
goto vm_nopage_error;
|
||||
|
||||
/*
|
||||
* Get the page, inc the use count, and return it
|
||||
*/
|
||||
* Get the page, inc the use count, and return it
|
||||
*/
|
||||
offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
|
||||
page = virt_to_page(__va(agpmem->memory->memory[offset]));
|
||||
get_page(page);
|
||||
|
||||
DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
|
||||
baddr, __va(agpmem->memory->memory[offset]), offset,
|
||||
page_count(page));
|
||||
DRM_DEBUG
|
||||
("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
|
||||
baddr, __va(agpmem->memory->memory[offset]), offset,
|
||||
page_count(page));
|
||||
|
||||
return page;
|
||||
}
|
||||
vm_nopage_error:
|
||||
return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
}
|
||||
vm_nopage_error:
|
||||
return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
}
|
||||
#else /* __OS_HAS_AGP */
|
||||
#else /* __OS_HAS_AGP */
|
||||
static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address)
|
||||
unsigned long address)
|
||||
{
|
||||
return NOPAGE_SIGBUS;
|
||||
}
|
||||
#endif /* __OS_HAS_AGP */
|
||||
#endif /* __OS_HAS_AGP */
|
||||
|
||||
/**
|
||||
* \c nopage method for shared virtual memory.
|
||||
|
@ -131,22 +135,24 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
|
|||
* \param vma virtual memory area.
|
||||
* \param address access address.
|
||||
* \return pointer to the page structure.
|
||||
*
|
||||
*
|
||||
* Get the the mapping, find the real physical page to map, get the page, and
|
||||
* return it.
|
||||
*/
|
||||
static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address)
|
||||
unsigned long address)
|
||||
{
|
||||
drm_map_t *map = (drm_map_t *)vma->vm_private_data;
|
||||
unsigned long offset;
|
||||
unsigned long i;
|
||||
struct page *page;
|
||||
drm_map_t *map = (drm_map_t *) vma->vm_private_data;
|
||||
unsigned long offset;
|
||||
unsigned long i;
|
||||
struct page *page;
|
||||
|
||||
if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
if (!map) return NOPAGE_OOM; /* Nothing allocated */
|
||||
if (address > vma->vm_end)
|
||||
return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
if (!map)
|
||||
return NOPAGE_OOM; /* Nothing allocated */
|
||||
|
||||
offset = address - vma->vm_start;
|
||||
offset = address - vma->vm_start;
|
||||
i = (unsigned long)map->handle + offset;
|
||||
page = (map->type == _DRM_CONSISTENT) ?
|
||||
virt_to_page((void *)i) : vmalloc_to_page((void *)i);
|
||||
|
@ -158,19 +164,18 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
|
|||
return page;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \c close method for shared virtual memory.
|
||||
*
|
||||
*
|
||||
* \param vma virtual memory area.
|
||||
*
|
||||
*
|
||||
* Deletes map information if we are the last
|
||||
* person to close a mapping and it's not in the global maplist.
|
||||
*/
|
||||
static void drm_vm_shm_close(struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_vma_entry_t *pt, *prev, *next;
|
||||
drm_map_t *map;
|
||||
drm_map_list_t *r_list;
|
||||
|
@ -186,7 +191,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
|
|||
down(&dev->struct_sem);
|
||||
for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
|
||||
next = pt->next;
|
||||
if (pt->vma->vm_private_data == map) found_maps++;
|
||||
if (pt->vma->vm_private_data == map)
|
||||
found_maps++;
|
||||
if (pt->vma == vma) {
|
||||
if (prev) {
|
||||
prev->next = pt->next;
|
||||
|
@ -199,8 +205,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
|
|||
}
|
||||
}
|
||||
/* We were the only map that was found */
|
||||
if(found_maps == 1 &&
|
||||
map->flags & _DRM_REMOVABLE) {
|
||||
if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
|
||||
/* Check to see if we are in the maplist, if we are not, then
|
||||
* we delete this mappings information.
|
||||
*/
|
||||
|
@ -208,10 +213,11 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
|
|||
list = &dev->maplist->head;
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
if (r_list->map == map) found_maps++;
|
||||
if (r_list->map == map)
|
||||
found_maps++;
|
||||
}
|
||||
|
||||
if(!found_maps) {
|
||||
if (!found_maps) {
|
||||
drm_dma_handle_t dmah;
|
||||
|
||||
switch (map->type) {
|
||||
|
@ -251,27 +257,29 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
|
|||
* \param vma virtual memory area.
|
||||
* \param address access address.
|
||||
* \return pointer to the page structure.
|
||||
*
|
||||
*
|
||||
* Determine the page number from the page offset and get it from drm_device_dma::pagelist.
|
||||
*/
|
||||
static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address)
|
||||
unsigned long address)
|
||||
{
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
unsigned long offset;
|
||||
unsigned long page_nr;
|
||||
struct page *page;
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
unsigned long offset;
|
||||
unsigned long page_nr;
|
||||
struct page *page;
|
||||
|
||||
if (!dma) return NOPAGE_SIGBUS; /* Error */
|
||||
if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
|
||||
if (!dma)
|
||||
return NOPAGE_SIGBUS; /* Error */
|
||||
if (address > vma->vm_end)
|
||||
return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
if (!dma->pagelist)
|
||||
return NOPAGE_OOM; /* Nothing allocated */
|
||||
|
||||
offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
|
||||
page_nr = offset >> PAGE_SHIFT;
|
||||
page = virt_to_page((dma->pagelist[page_nr] +
|
||||
(offset & (~PAGE_MASK))));
|
||||
offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
|
||||
page_nr = offset >> PAGE_SHIFT;
|
||||
page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK))));
|
||||
|
||||
get_page(page);
|
||||
|
||||
|
@ -285,13 +293,13 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
|
|||
* \param vma virtual memory area.
|
||||
* \param address access address.
|
||||
* \return pointer to the page structure.
|
||||
*
|
||||
*
|
||||
* Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
|
||||
*/
|
||||
static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address)
|
||||
unsigned long address)
|
||||
{
|
||||
drm_map_t *map = (drm_map_t *)vma->vm_private_data;
|
||||
drm_map_t *map = (drm_map_t *) vma->vm_private_data;
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
|
@ -300,10 +308,12 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
|
|||
unsigned long page_offset;
|
||||
struct page *page;
|
||||
|
||||
if (!entry) return NOPAGE_SIGBUS; /* Error */
|
||||
if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */
|
||||
|
||||
if (!entry)
|
||||
return NOPAGE_SIGBUS; /* Error */
|
||||
if (address > vma->vm_end)
|
||||
return NOPAGE_SIGBUS; /* Disallow mremap */
|
||||
if (!entry->pagelist)
|
||||
return NOPAGE_OOM; /* Nothing allocated */
|
||||
|
||||
offset = address - vma->vm_start;
|
||||
map_offset = map->offset - (unsigned long)dev->sg->virtual;
|
||||
|
@ -314,76 +324,78 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
|
|||
return page;
|
||||
}
|
||||
|
||||
|
||||
static struct page *drm_vm_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int *type) {
|
||||
if (type) *type = VM_FAULT_MINOR;
|
||||
unsigned long address, int *type)
|
||||
{
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return drm_do_vm_nopage(vma, address);
|
||||
}
|
||||
|
||||
static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int *type) {
|
||||
if (type) *type = VM_FAULT_MINOR;
|
||||
unsigned long address, int *type)
|
||||
{
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return drm_do_vm_shm_nopage(vma, address);
|
||||
}
|
||||
|
||||
static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int *type) {
|
||||
if (type) *type = VM_FAULT_MINOR;
|
||||
unsigned long address, int *type)
|
||||
{
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return drm_do_vm_dma_nopage(vma, address);
|
||||
}
|
||||
|
||||
static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
int *type) {
|
||||
if (type) *type = VM_FAULT_MINOR;
|
||||
unsigned long address, int *type)
|
||||
{
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return drm_do_vm_sg_nopage(vma, address);
|
||||
}
|
||||
|
||||
/** AGP virtual memory operations */
|
||||
static struct vm_operations_struct drm_vm_ops = {
|
||||
static struct vm_operations_struct drm_vm_ops = {
|
||||
.nopage = drm_vm_nopage,
|
||||
.open = drm_vm_open,
|
||||
.close = drm_vm_close,
|
||||
.open = drm_vm_open,
|
||||
.close = drm_vm_close,
|
||||
};
|
||||
|
||||
/** Shared virtual memory operations */
|
||||
static struct vm_operations_struct drm_vm_shm_ops = {
|
||||
static struct vm_operations_struct drm_vm_shm_ops = {
|
||||
.nopage = drm_vm_shm_nopage,
|
||||
.open = drm_vm_open,
|
||||
.close = drm_vm_shm_close,
|
||||
.open = drm_vm_open,
|
||||
.close = drm_vm_shm_close,
|
||||
};
|
||||
|
||||
/** DMA virtual memory operations */
|
||||
static struct vm_operations_struct drm_vm_dma_ops = {
|
||||
static struct vm_operations_struct drm_vm_dma_ops = {
|
||||
.nopage = drm_vm_dma_nopage,
|
||||
.open = drm_vm_open,
|
||||
.close = drm_vm_close,
|
||||
.open = drm_vm_open,
|
||||
.close = drm_vm_close,
|
||||
};
|
||||
|
||||
/** Scatter-gather virtual memory operations */
|
||||
static struct vm_operations_struct drm_vm_sg_ops = {
|
||||
static struct vm_operations_struct drm_vm_sg_ops = {
|
||||
.nopage = drm_vm_sg_nopage,
|
||||
.open = drm_vm_open,
|
||||
.close = drm_vm_close,
|
||||
.open = drm_vm_open,
|
||||
.close = drm_vm_close,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \c open method for shared virtual memory.
|
||||
*
|
||||
*
|
||||
* \param vma virtual memory area.
|
||||
*
|
||||
*
|
||||
* Create a new drm_vma_entry structure as the \p vma private data entry and
|
||||
* add it to drm_device::vmalist.
|
||||
*/
|
||||
static void drm_vm_open(struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_vma_entry_t *vma_entry;
|
||||
|
||||
DRM_DEBUG("0x%08lx,0x%08lx\n",
|
||||
|
@ -393,26 +405,26 @@ static void drm_vm_open(struct vm_area_struct *vma)
|
|||
vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
|
||||
if (vma_entry) {
|
||||
down(&dev->struct_sem);
|
||||
vma_entry->vma = vma;
|
||||
vma_entry->vma = vma;
|
||||
vma_entry->next = dev->vmalist;
|
||||
vma_entry->pid = current->pid;
|
||||
dev->vmalist = vma_entry;
|
||||
vma_entry->pid = current->pid;
|
||||
dev->vmalist = vma_entry;
|
||||
up(&dev->struct_sem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \c close method for all virtual memory types.
|
||||
*
|
||||
*
|
||||
* \param vma virtual memory area.
|
||||
*
|
||||
*
|
||||
* Search the \p vma private data entry in drm_device::vmalist, unlink it, and
|
||||
* free it.
|
||||
*/
|
||||
static void drm_vm_close(struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_vma_entry_t *pt, *prev;
|
||||
|
||||
DRM_DEBUG("0x%08lx,0x%08lx\n",
|
||||
|
@ -440,43 +452,44 @@ static void drm_vm_close(struct vm_area_struct *vma)
|
|||
* \param filp file pointer.
|
||||
* \param vma virtual memory area.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
*
|
||||
* Sets the virtual memory area operations structure to vm_dma_ops, the file
|
||||
* pointer, and calls vm_open().
|
||||
*/
|
||||
static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev;
|
||||
drm_device_dma_t *dma;
|
||||
unsigned long length = vma->vm_end - vma->vm_start;
|
||||
unsigned long length = vma->vm_end - vma->vm_start;
|
||||
|
||||
lock_kernel();
|
||||
dev = priv->head->dev;
|
||||
dma = dev->dma;
|
||||
dev = priv->head->dev;
|
||||
dma = dev->dma;
|
||||
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
|
||||
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
|
||||
|
||||
/* Length must match exact page count */
|
||||
/* Length must match exact page count */
|
||||
if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
|
||||
unlock_kernel();
|
||||
return -EINVAL;
|
||||
}
|
||||
unlock_kernel();
|
||||
|
||||
vma->vm_ops = &drm_vm_dma_ops;
|
||||
vma->vm_ops = &drm_vm_dma_ops;
|
||||
|
||||
vma->vm_flags |= VM_RESERVED; /* Don't swap */
|
||||
vma->vm_flags |= VM_RESERVED; /* Don't swap */
|
||||
|
||||
vma->vm_file = filp; /* Needed for drm_vm_open() */
|
||||
vma->vm_file = filp; /* Needed for drm_vm_open() */
|
||||
drm_vm_open(vma);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long drm_core_get_map_ofs(drm_map_t *map)
|
||||
unsigned long drm_core_get_map_ofs(drm_map_t * map)
|
||||
{
|
||||
return map->offset;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_core_get_map_ofs);
|
||||
|
||||
unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
|
||||
|
@ -487,6 +500,7 @@ unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
|
|||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_core_get_reg_ofs);
|
||||
|
||||
/**
|
||||
|
@ -495,7 +509,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
|
|||
* \param filp file pointer.
|
||||
* \param vma virtual memory area.
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
*
|
||||
* If the virtual memory area has no offset associated with it then it's a DMA
|
||||
* area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
|
||||
* checks that the restricted flag is not set, sets the virtual memory operations
|
||||
|
@ -504,17 +518,18 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
|
|||
*/
|
||||
int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_map_t *map = NULL;
|
||||
drm_map_list_t *r_list;
|
||||
unsigned long offset = 0;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_map_t *map = NULL;
|
||||
drm_map_list_t *r_list;
|
||||
unsigned long offset = 0;
|
||||
struct list_head *list;
|
||||
|
||||
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
|
||||
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
|
||||
|
||||
if ( !priv->authenticated ) return -EACCES;
|
||||
if (!priv->authenticated)
|
||||
return -EACCES;
|
||||
|
||||
/* We check for "dma". On Apple's UniNorth, it's valid to have
|
||||
* the AGP mapped at physical address 0
|
||||
|
@ -522,61 +537,66 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
*/
|
||||
if (!VM_OFFSET(vma)
|
||||
#if __OS_HAS_AGP
|
||||
&& (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
|
||||
&& (!dev->agp
|
||||
|| dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
|
||||
#endif
|
||||
)
|
||||
return drm_mmap_dma(filp, vma);
|
||||
|
||||
/* A sequential search of a linked list is
|
||||
fine here because: 1) there will only be
|
||||
about 5-10 entries in the list and, 2) a
|
||||
DRI client only has to do this mapping
|
||||
once, so it doesn't have to be optimized
|
||||
for performance, even if the list was a
|
||||
bit longer. */
|
||||
/* A sequential search of a linked list is
|
||||
fine here because: 1) there will only be
|
||||
about 5-10 entries in the list and, 2) a
|
||||
DRI client only has to do this mapping
|
||||
once, so it doesn't have to be optimized
|
||||
for performance, even if the list was a
|
||||
bit longer. */
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
|
||||
r_list = list_entry(list, drm_map_list_t, head);
|
||||
map = r_list->map;
|
||||
if (!map) continue;
|
||||
if (!map)
|
||||
continue;
|
||||
if (r_list->user_token == VM_OFFSET(vma))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
|
||||
if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
|
||||
return -EPERM;
|
||||
|
||||
/* Check for valid size. */
|
||||
if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
|
||||
/* Check for valid size. */
|
||||
if (map->size != vma->vm_end - vma->vm_start)
|
||||
return -EINVAL;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
|
||||
vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
|
||||
#else
|
||||
/* Ye gads this is ugly. With more thought
|
||||
we could move this up higher and use
|
||||
`protection_map' instead. */
|
||||
vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
|
||||
__pte(pgprot_val(vma->vm_page_prot)))));
|
||||
/* Ye gads this is ugly. With more thought
|
||||
we could move this up higher and use
|
||||
`protection_map' instead. */
|
||||
vma->vm_page_prot =
|
||||
__pgprot(pte_val
|
||||
(pte_wrprotect
|
||||
(__pte(pgprot_val(vma->vm_page_prot)))));
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (map->type) {
|
||||
case _DRM_AGP:
|
||||
if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
|
||||
/*
|
||||
* On some platforms we can't talk to bus dma address from the CPU, so for
|
||||
* memory of type DRM_AGP, we'll deal with sorting out the real physical
|
||||
* pages and mappings in nopage()
|
||||
*/
|
||||
case _DRM_AGP:
|
||||
if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
|
||||
/*
|
||||
* On some platforms we can't talk to bus dma address from the CPU, so for
|
||||
* memory of type DRM_AGP, we'll deal with sorting out the real physical
|
||||
* pages and mappings in nopage()
|
||||
*/
|
||||
#if defined(__powerpc__)
|
||||
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
|
||||
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
|
||||
#endif
|
||||
vma->vm_ops = &drm_vm_ops;
|
||||
break;
|
||||
}
|
||||
/* fall through to _DRM_FRAME_BUFFER... */
|
||||
vma->vm_ops = &drm_vm_ops;
|
||||
break;
|
||||
}
|
||||
/* fall through to _DRM_FRAME_BUFFER... */
|
||||
case _DRM_FRAME_BUFFER:
|
||||
case _DRM_REGISTERS:
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
@ -591,27 +611,25 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
#endif
|
||||
vma->vm_flags |= VM_IO; /* not in core dump */
|
||||
#if defined(__ia64__)
|
||||
if (efi_range_is_wc(vma->vm_start, vma->vm_end -
|
||||
vma->vm_start))
|
||||
if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
|
||||
vma->vm_page_prot =
|
||||
pgprot_writecombine(vma->vm_page_prot);
|
||||
pgprot_writecombine(vma->vm_page_prot);
|
||||
else
|
||||
vma->vm_page_prot =
|
||||
pgprot_noncached(vma->vm_page_prot);
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
#endif
|
||||
offset = dev->driver->get_reg_ofs(dev);
|
||||
#ifdef __sparc__
|
||||
if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
|
||||
(map->offset + offset) >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
(map->offset + offset) >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
#else
|
||||
if (io_remap_pfn_range(vma, vma->vm_start,
|
||||
(map->offset + offset) >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
(map->offset + offset) >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
#endif
|
||||
return -EAGAIN;
|
||||
return -EAGAIN;
|
||||
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
|
||||
" offset = 0x%lx\n",
|
||||
map->type,
|
||||
|
@ -624,22 +642,23 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
* allocate in a different way */
|
||||
vma->vm_ops = &drm_vm_shm_ops;
|
||||
vma->vm_private_data = (void *)map;
|
||||
/* Don't let this area swap. Change when
|
||||
DRM_KERNEL advisory is supported. */
|
||||
/* Don't let this area swap. Change when
|
||||
DRM_KERNEL advisory is supported. */
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
break;
|
||||
case _DRM_SCATTER_GATHER:
|
||||
vma->vm_ops = &drm_vm_sg_ops;
|
||||
vma->vm_private_data = (void *)map;
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL; /* This should never happen. */
|
||||
}
|
||||
vma->vm_flags |= VM_RESERVED; /* Don't swap */
|
||||
vma->vm_flags |= VM_RESERVED; /* Don't swap */
|
||||
|
||||
vma->vm_file = filp; /* Needed for drm_vm_open() */
|
||||
vma->vm_file = filp; /* Needed for drm_vm_open() */
|
||||
drm_vm_open(vma);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_mmap);
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
|
||||
#include "ffb_drv.h"
|
||||
|
||||
static int DRM(alloc_queue)(drm_device_t *dev, int is_2d_only)
|
||||
{
|
||||
static int DRM(alloc_queue) (drm_device_t * dev, int is_2d_only) {
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
int i;
|
||||
|
||||
|
@ -37,7 +36,7 @@ static int DRM(alloc_queue)(drm_device_t *dev, int is_2d_only)
|
|||
return i + 1;
|
||||
}
|
||||
|
||||
static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
|
||||
static void ffb_save_context(ffb_dev_priv_t * fpriv, int idx)
|
||||
{
|
||||
ffb_fbcPtr ffb = fpriv->regs;
|
||||
struct ffb_hw_context *ctx;
|
||||
|
@ -94,36 +93,36 @@ static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
|
|||
|
||||
/* Capture rendering attributes. */
|
||||
|
||||
ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */
|
||||
ctx->wid = upa_readl(&ffb->wid); /* Current WID */
|
||||
ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */
|
||||
ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */
|
||||
ctx->consty = upa_readl(&ffb->consty); /* Constant Y */
|
||||
ctx->constz = upa_readl(&ffb->constz); /* Constant Z */
|
||||
ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */
|
||||
ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */
|
||||
ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */
|
||||
ctx->wid = upa_readl(&ffb->wid); /* Current WID */
|
||||
ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */
|
||||
ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */
|
||||
ctx->consty = upa_readl(&ffb->consty); /* Constant Y */
|
||||
ctx->constz = upa_readl(&ffb->constz); /* Constant Z */
|
||||
ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */
|
||||
ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */
|
||||
ctx->vclipmin = upa_readl(&ffb->vclipmin); /* Primary XY clip, minimum */
|
||||
ctx->vclipmax = upa_readl(&ffb->vclipmax); /* Primary XY clip, maximum */
|
||||
ctx->vclipzmin = upa_readl(&ffb->vclipzmin); /* Primary Z clip, minimum */
|
||||
ctx->vclipzmax = upa_readl(&ffb->vclipzmax); /* Primary Z clip, maximum */
|
||||
ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */
|
||||
ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */
|
||||
ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */
|
||||
ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */
|
||||
ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */
|
||||
ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */
|
||||
ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */
|
||||
ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */
|
||||
ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */
|
||||
ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */
|
||||
ctx->blendc1 = upa_readl(&ffb->blendc1); /* Alpha Blend Color 1 */
|
||||
ctx->blendc2 = upa_readl(&ffb->blendc2); /* Alpha Blend Color 2 */
|
||||
ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */
|
||||
ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */
|
||||
ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */
|
||||
ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */
|
||||
ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */
|
||||
ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */
|
||||
ctx->matchab = upa_readl(&ffb->matchab); /* Buffer A/B Match Ops */
|
||||
ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */
|
||||
ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */
|
||||
ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */
|
||||
ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */
|
||||
ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */
|
||||
ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */
|
||||
ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */
|
||||
ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */
|
||||
ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */
|
||||
ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */
|
||||
ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */
|
||||
ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */
|
||||
ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */
|
||||
ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */
|
||||
|
||||
/* Auxiliary Clips. */
|
||||
ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min);
|
||||
|
@ -135,9 +134,9 @@ static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
|
|||
ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min);
|
||||
ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max);
|
||||
|
||||
ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */
|
||||
ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */
|
||||
ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */
|
||||
ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */
|
||||
ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */
|
||||
ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */
|
||||
ctx->fontinc = upa_readl(&ffb->fontinc); /* Font X/Y Increment */
|
||||
|
||||
/* These registers/features only exist on FFB2 and later chips. */
|
||||
|
@ -145,12 +144,12 @@ static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
|
|||
ctx->dcss1 = upa_readl(&ffb->dcss1); /* Depth Cue Scale Slope 1 */
|
||||
ctx->dcss2 = upa_readl(&ffb->dcss2); /* Depth Cue Scale Slope 2 */
|
||||
ctx->dcss2 = upa_readl(&ffb->dcss3); /* Depth Cue Scale Slope 3 */
|
||||
ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */
|
||||
ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */
|
||||
ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */
|
||||
ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */
|
||||
ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */
|
||||
ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */
|
||||
ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */
|
||||
ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */
|
||||
ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */
|
||||
ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */
|
||||
ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */
|
||||
ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */
|
||||
|
||||
/* And stencil/stencilctl only exists on FFB2+ and later
|
||||
* due to the introduction of 3DRAM-III.
|
||||
|
@ -170,7 +169,7 @@ static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx)
|
|||
ctx->ucsr = upa_readl(&ffb->ucsr);
|
||||
}
|
||||
|
||||
static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
|
||||
static void ffb_restore_context(ffb_dev_priv_t * fpriv, int old, int idx)
|
||||
{
|
||||
ffb_fbcPtr ffb = fpriv->regs;
|
||||
struct ffb_hw_context *ctx;
|
||||
|
@ -193,7 +192,7 @@ static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
|
|||
|
||||
upa_writel(ctx->ppc, &ffb->ppc);
|
||||
upa_writel(ctx->wid, &ffb->wid);
|
||||
upa_writel(ctx->fg, &ffb->fg);
|
||||
upa_writel(ctx->fg, &ffb->fg);
|
||||
upa_writel(ctx->bg, &ffb->bg);
|
||||
upa_writel(ctx->xclip, &ffb->xclip);
|
||||
upa_writel(ctx->fbc, &ffb->fbc);
|
||||
|
@ -237,36 +236,36 @@ static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
|
|||
|
||||
/* Restore rendering attributes. */
|
||||
|
||||
upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */
|
||||
upa_writel(ctx->wid, &ffb->wid); /* Current WID */
|
||||
upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */
|
||||
upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */
|
||||
upa_writel(ctx->consty, &ffb->consty); /* Constant Y */
|
||||
upa_writel(ctx->constz, &ffb->constz); /* Constant Z */
|
||||
upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */
|
||||
upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */
|
||||
upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */
|
||||
upa_writel(ctx->wid, &ffb->wid); /* Current WID */
|
||||
upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */
|
||||
upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */
|
||||
upa_writel(ctx->consty, &ffb->consty); /* Constant Y */
|
||||
upa_writel(ctx->constz, &ffb->constz); /* Constant Z */
|
||||
upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */
|
||||
upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */
|
||||
upa_writel(ctx->vclipmin, &ffb->vclipmin); /* Primary XY clip, minimum */
|
||||
upa_writel(ctx->vclipmax, &ffb->vclipmax); /* Primary XY clip, maximum */
|
||||
upa_writel(ctx->vclipzmin, &ffb->vclipzmin); /* Primary Z clip, minimum */
|
||||
upa_writel(ctx->vclipzmax, &ffb->vclipzmax); /* Primary Z clip, maximum */
|
||||
upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */
|
||||
upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */
|
||||
upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */
|
||||
upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */
|
||||
upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */
|
||||
upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */
|
||||
upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */
|
||||
upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */
|
||||
upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */
|
||||
upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */
|
||||
upa_writel(ctx->blendc1, &ffb->blendc1); /* Alpha Blend Color 1 */
|
||||
upa_writel(ctx->blendc2, &ffb->blendc2); /* Alpha Blend Color 2 */
|
||||
upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */
|
||||
upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */
|
||||
upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */
|
||||
upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */
|
||||
upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */
|
||||
upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */
|
||||
upa_writel(ctx->matchab, &ffb->matchab); /* Buffer A/B Match Ops */
|
||||
upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */
|
||||
upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */
|
||||
upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */
|
||||
upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */
|
||||
upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */
|
||||
upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */
|
||||
upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */
|
||||
upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */
|
||||
upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */
|
||||
upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */
|
||||
upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */
|
||||
upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */
|
||||
upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */
|
||||
upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */
|
||||
|
||||
/* Auxiliary Clips. */
|
||||
upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min);
|
||||
|
@ -278,9 +277,9 @@ static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx)
|
|||
upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min);
|
||||
upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max);
|
||||
|
||||
upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */
|
||||
upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */
|
||||
upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */
|
||||
upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */
|
||||
upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */
|
||||
upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */
|
||||
upa_writel(ctx->fontinc, &ffb->fontinc); /* Font X/Y Increment */
|
||||
|
||||
/* These registers/features only exist on FFB2 and later chips. */
|
||||
|
@ -354,91 +353,87 @@ static void FFBWait(ffb_fbcPtr ffb)
|
|||
} while (--limit);
|
||||
}
|
||||
|
||||
int ffb_driver_context_switch(drm_device_t *dev, int old, int new)
|
||||
int ffb_driver_context_switch(drm_device_t * dev, int old, int new)
|
||||
{
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
|
||||
#ifdef DRM_DMA_HISTOGRAM
|
||||
dev->ctx_start = get_cycles();
|
||||
dev->ctx_start = get_cycles();
|
||||
#endif
|
||||
|
||||
DRM_DEBUG("Context switch from %d to %d\n", old, new);
|
||||
|
||||
if (new == dev->last_context ||
|
||||
dev->last_context == 0) {
|
||||
DRM_DEBUG("Context switch from %d to %d\n", old, new);
|
||||
|
||||
if (new == dev->last_context || dev->last_context == 0) {
|
||||
dev->last_context = new;
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FFBWait(fpriv->regs);
|
||||
ffb_save_context(fpriv, old);
|
||||
ffb_restore_context(fpriv, old, new);
|
||||
FFBWait(fpriv->regs);
|
||||
|
||||
|
||||
dev->last_context = new;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_ctx_res_t res;
|
||||
drm_ctx_t ctx;
|
||||
int i;
|
||||
drm_ctx_res_t res;
|
||||
drm_ctx_t ctx;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
|
||||
if (copy_from_user(&res, (drm_ctx_res_t __user *)arg, sizeof(res)))
|
||||
if (copy_from_user(&res, (drm_ctx_res_t __user *) arg, sizeof(res)))
|
||||
return -EFAULT;
|
||||
if (res.count >= DRM_RESERVED_CONTEXTS) {
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
|
||||
ctx.handle = i;
|
||||
if (copy_to_user(&res.contexts[i],
|
||||
&i,
|
||||
sizeof(i)))
|
||||
if (copy_to_user(&res.contexts[i], &i, sizeof(i)))
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
res.count = DRM_RESERVED_CONTEXTS;
|
||||
if (copy_to_user((drm_ctx_res_t __user *)arg, &res, sizeof(res)))
|
||||
if (copy_to_user((drm_ctx_res_t __user *) arg, &res, sizeof(res)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_ctx_t ctx;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_ctx_t ctx;
|
||||
int idx;
|
||||
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
idx = DRM(alloc_queue)(dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
|
||||
idx = DRM(alloc_queue) (dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
|
||||
if (idx < 0)
|
||||
return -ENFILE;
|
||||
|
||||
DRM_DEBUG("%d\n", ctx.handle);
|
||||
ctx.handle = idx;
|
||||
if (copy_to_user((drm_ctx_t __user *)arg, &ctx, sizeof(ctx)))
|
||||
if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
struct ffb_hw_context *hwctx;
|
||||
drm_ctx_t ctx;
|
||||
int idx;
|
||||
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
|
||||
idx = ctx.handle;
|
||||
|
@ -458,16 +453,16 @@ int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
}
|
||||
|
||||
int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
struct ffb_hw_context *hwctx;
|
||||
drm_ctx_t ctx;
|
||||
int idx;
|
||||
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
|
||||
idx = ctx.handle;
|
||||
|
@ -483,31 +478,31 @@ int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
else
|
||||
ctx.flags = 0;
|
||||
|
||||
if (copy_to_user((drm_ctx_t __user *)arg, &ctx, sizeof(ctx)))
|
||||
if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ffb_driver_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
int ffb_driver_switchctx(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_ctx_t ctx;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
DRM_DEBUG("%d\n", ctx.handle);
|
||||
return ffb_driver_context_switch(dev, dev->last_context, ctx.handle);
|
||||
}
|
||||
|
||||
int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_ctx_t ctx;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
DRM_DEBUG("%d\n", ctx.handle);
|
||||
|
||||
|
@ -515,15 +510,15 @@ int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
}
|
||||
|
||||
int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_ctx_t ctx;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
drm_ctx_t ctx;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
int idx;
|
||||
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
|
||||
if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
|
||||
return -EFAULT;
|
||||
DRM_DEBUG("%d\n", ctx.handle);
|
||||
|
||||
|
@ -544,7 +539,8 @@ void ffb_set_context_ioctls(void)
|
|||
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx;
|
||||
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx;
|
||||
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx;
|
||||
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = ffb_driver_switchctx;
|
||||
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func =
|
||||
ffb_driver_switchctx;
|
||||
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx;
|
||||
DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx;
|
||||
|
||||
|
|
|
@ -33,13 +33,13 @@ typedef struct _ffb_position_t {
|
|||
|
||||
static ffb_position_t *ffb_position;
|
||||
|
||||
static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
|
||||
static void get_ffb_type(ffb_dev_priv_t * ffb_priv, int instance)
|
||||
{
|
||||
volatile unsigned char *strap_bits;
|
||||
unsigned char val;
|
||||
|
||||
strap_bits = (volatile unsigned char *)
|
||||
(ffb_priv->card_phys_base + 0x00200000UL);
|
||||
(ffb_priv->card_phys_base + 0x00200000UL);
|
||||
|
||||
/* Don't ask, you have to read the value twice for whatever
|
||||
* reason to get correct contents.
|
||||
|
@ -61,7 +61,8 @@ static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
|
|||
break;
|
||||
case (0x1 << 5) | (0x0 << 3):
|
||||
ffb_priv->ffb_type = ffb2_prototype;
|
||||
printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n", instance);
|
||||
printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n",
|
||||
instance);
|
||||
break;
|
||||
case (0x1 << 5) | (0x1 << 3):
|
||||
ffb_priv->ffb_type = ffb2_vertical;
|
||||
|
@ -81,12 +82,13 @@ static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
|
|||
break;
|
||||
default:
|
||||
ffb_priv->ffb_type = ffb2_vertical;
|
||||
printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n", instance, val);
|
||||
printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n",
|
||||
instance, val);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
static void ffb_apply_upa_parent_ranges(int parent,
|
||||
static void ffb_apply_upa_parent_ranges(int parent,
|
||||
struct linux_prom64_registers *regs)
|
||||
{
|
||||
struct linux_prom64_ranges ranges[PROMREG_MAX];
|
||||
|
@ -97,7 +99,8 @@ static void ffb_apply_upa_parent_ranges(int parent,
|
|||
if (strcmp(name, "upa") != 0)
|
||||
return;
|
||||
|
||||
len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
|
||||
len =
|
||||
prom_getproperty(parent, "ranges", (void *)ranges, sizeof(ranges));
|
||||
if (len <= 0)
|
||||
return;
|
||||
|
||||
|
@ -117,11 +120,11 @@ static void ffb_apply_upa_parent_ranges(int parent,
|
|||
return;
|
||||
}
|
||||
|
||||
static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
|
||||
static int ffb_init_one(drm_device_t * dev, int prom_node, int parent_node,
|
||||
int instance)
|
||||
{
|
||||
struct linux_prom64_registers regs[2*PROMREG_MAX];
|
||||
ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
|
||||
struct linux_prom64_registers regs[2 * PROMREG_MAX];
|
||||
ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
int i;
|
||||
|
||||
ffb_priv->prom_node = prom_node;
|
||||
|
@ -132,27 +135,27 @@ static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
|
|||
ffb_apply_upa_parent_ranges(parent_node, ®s[0]);
|
||||
ffb_priv->card_phys_base = regs[0].phys_addr;
|
||||
ffb_priv->regs = (ffb_fbcPtr)
|
||||
(regs[0].phys_addr + 0x00600000UL);
|
||||
(regs[0].phys_addr + 0x00600000UL);
|
||||
get_ffb_type(ffb_priv, instance);
|
||||
for (i = 0; i < FFB_MAX_CTXS; i++)
|
||||
ffb_priv->hw_state[i] = NULL;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev;
|
||||
drm_map_list_t *r_list;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev;
|
||||
drm_map_list_t *r_list;
|
||||
struct list_head *list;
|
||||
drm_map_t *map;
|
||||
drm_map_t *map;
|
||||
|
||||
if (!priv || (dev = priv->dev) == NULL)
|
||||
return NULL;
|
||||
|
||||
list_for_each(list, &dev->maplist->head) {
|
||||
r_list = (drm_map_list_t *)list;
|
||||
r_list = (drm_map_list_t *) list;
|
||||
map = r_list->map;
|
||||
if (!map)
|
||||
continue;
|
||||
|
@ -166,8 +169,7 @@ static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
|
|||
unsigned long ffb_get_unmapped_area(struct file *filp,
|
||||
unsigned long hint,
|
||||
unsigned long len,
|
||||
unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
|
||||
unsigned long addr = -ENOMEM;
|
||||
|
@ -175,8 +177,7 @@ unsigned long ffb_get_unmapped_area(struct file *filp,
|
|||
if (!map)
|
||||
return get_unmapped_area(NULL, hint, len, pgoff, flags);
|
||||
|
||||
if (map->type == _DRM_FRAME_BUFFER ||
|
||||
map->type == _DRM_REGISTERS) {
|
||||
if (map->type == _DRM_FRAME_BUFFER || map->type == _DRM_REGISTERS) {
|
||||
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
|
||||
addr = get_fb_unmapped_area(filp, hint, len, pgoff, flags);
|
||||
#else
|
||||
|
@ -187,7 +188,7 @@ unsigned long ffb_get_unmapped_area(struct file *filp,
|
|||
|
||||
addr = get_unmapped_area(NULL, hint, len + slack, pgoff, flags);
|
||||
if (!(addr & ~PAGE_MASK)) {
|
||||
unsigned long kvirt = (unsigned long) map->handle;
|
||||
unsigned long kvirt = (unsigned long)map->handle;
|
||||
|
||||
if ((kvirt & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
|
||||
unsigned long koff, aoff;
|
||||
|
@ -207,9 +208,9 @@ unsigned long ffb_get_unmapped_area(struct file *filp,
|
|||
return addr;
|
||||
}
|
||||
|
||||
static int ffb_presetup(drm_device_t *dev)
|
||||
static int ffb_presetup(drm_device_t * dev)
|
||||
{
|
||||
ffb_dev_priv_t *ffb_priv;
|
||||
ffb_dev_priv_t *ffb_priv;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
|
@ -224,14 +225,11 @@ static int ffb_presetup(drm_device_t *dev)
|
|||
memset(ffb_priv, 0, sizeof(*ffb_priv));
|
||||
dev->dev_private = ffb_priv;
|
||||
|
||||
ret = ffb_init_one(dev,
|
||||
ffb_position[i].node,
|
||||
ffb_position[i].root,
|
||||
i);
|
||||
ret = ffb_init_one(dev, ffb_position[i].node, ffb_position[i].root, i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ffb_driver_release(drm_device_t *dev, struct file *filp)
|
||||
static void ffb_driver_release(drm_device_t * dev, struct file *filp)
|
||||
{
|
||||
ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
|
||||
|
@ -239,84 +237,82 @@ static void ffb_driver_release(drm_device_t *dev, struct file *filp)
|
|||
|
||||
idx = context - 1;
|
||||
if (fpriv &&
|
||||
context != DRM_KERNEL_CONTEXT &&
|
||||
fpriv->hw_state[idx] != NULL) {
|
||||
context != DRM_KERNEL_CONTEXT && fpriv->hw_state[idx] != NULL) {
|
||||
kfree(fpriv->hw_state[idx]);
|
||||
fpriv->hw_state[idx] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ffb_driver_pretakedown(drm_device_t *dev)
|
||||
static void ffb_driver_pretakedown(drm_device_t * dev)
|
||||
{
|
||||
if (dev->dev_private) kfree(dev->dev_private);
|
||||
if (dev->dev_private)
|
||||
kfree(dev->dev_private);
|
||||
}
|
||||
|
||||
static int ffb_driver_postcleanup(drm_device_t *dev)
|
||||
static int ffb_driver_postcleanup(drm_device_t * dev)
|
||||
{
|
||||
if (ffb_position != NULL) kfree(ffb_position);
|
||||
if (ffb_position != NULL)
|
||||
kfree(ffb_position);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev, drm_lock_t *lock)
|
||||
static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev,
|
||||
drm_lock_t * lock)
|
||||
{
|
||||
dev->lock.filp = 0;
|
||||
{
|
||||
__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
|
||||
unsigned int old, new, prev, ctx;
|
||||
|
||||
|
||||
ctx = lock->context;
|
||||
do {
|
||||
old = *plock;
|
||||
new = ctx;
|
||||
old = *plock;
|
||||
new = ctx;
|
||||
prev = cmpxchg(plock, old, new);
|
||||
} while (prev != old);
|
||||
}
|
||||
wake_up_interruptible(&dev->lock.lock_queue);
|
||||
}
|
||||
|
||||
static unsigned long ffb_driver_get_map_ofs(drm_map_t *map)
|
||||
static unsigned long ffb_driver_get_map_ofs(drm_map_t * map)
|
||||
{
|
||||
return (map->offset & 0xffffffff);
|
||||
}
|
||||
|
||||
static unsigned long ffb_driver_get_reg_ofs(drm_device_t *dev)
|
||||
static unsigned long ffb_driver_get_reg_ofs(drm_device_t * dev)
|
||||
{
|
||||
ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
|
||||
|
||||
if (ffb_priv)
|
||||
return ffb_priv->card_phys_base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
|
||||
|
||||
if (ffb_priv)
|
||||
return ffb_priv->card_phys_base;
|
||||
|
||||
static int postinit( struct drm_device *dev, unsigned long flags )
|
||||
{
|
||||
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE,
|
||||
dev->minor
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int version( drm_version_t *version )
|
||||
static int postinit(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR, DRIVER_PATCHLEVEL, DRIVER_DATE, dev->minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int version(drm_version_t * version)
|
||||
{
|
||||
int len;
|
||||
|
||||
version->version_major = DRIVER_MAJOR;
|
||||
version->version_minor = DRIVER_MINOR;
|
||||
version->version_patchlevel = DRIVER_PATCHLEVEL;
|
||||
DRM_COPY( version->name, DRIVER_NAME );
|
||||
DRM_COPY( version->date, DRIVER_DATE );
|
||||
DRM_COPY( version->desc, DRIVER_DESC );
|
||||
DRM_COPY(version->name, DRIVER_NAME);
|
||||
DRM_COPY(version->date, DRIVER_DATE);
|
||||
DRM_COPY(version->desc, DRIVER_DESC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static drm_ioctl_desc_t ioctls[] = {
|
||||
|
||||
|
||||
};
|
||||
|
||||
static struct drm_driver driver = {
|
||||
|
@ -335,14 +331,15 @@ static struct drm_driver driver = {
|
|||
.ioctls = ioctls,
|
||||
.num_ioctls = DRM_ARRAY_SIZE(ioctls),
|
||||
.fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
},
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
}
|
||||
,
|
||||
};
|
||||
|
||||
static int __init ffb_init(void)
|
||||
|
@ -357,6 +354,6 @@ static void __exit ffb_exit(void)
|
|||
module_init(ffb_init);
|
||||
module_exit(ffb_exit);
|
||||
|
||||
MODULE_AUTHOR( DRIVER_AUTHOR );
|
||||
MODULE_DESCRIPTION( DRIVER_DESC );
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/* Auxilliary clips. */
|
||||
typedef struct {
|
||||
typedef struct {
|
||||
volatile unsigned int min;
|
||||
volatile unsigned int max;
|
||||
} ffb_auxclip, *ffb_auxclipPtr;
|
||||
|
@ -15,172 +15,265 @@ typedef struct _ffb_fbc {
|
|||
/* Next vertex registers, on the right we list which drawops
|
||||
* use said register and the logical name the register has in
|
||||
* that context.
|
||||
*/ /* DESCRIPTION DRAWOP(NAME) */
|
||||
/*0x00*/unsigned int pad1[3]; /* Reserved */
|
||||
/*0x0c*/volatile unsigned int alpha; /* ALPHA Transparency */
|
||||
/*0x10*/volatile unsigned int red; /* RED */
|
||||
/*0x14*/volatile unsigned int green; /* GREEN */
|
||||
/*0x18*/volatile unsigned int blue; /* BLUE */
|
||||
/*0x1c*/volatile unsigned int z; /* DEPTH */
|
||||
/*0x20*/volatile unsigned int y; /* Y triangle(DOYF) */
|
||||
/* aadot(DYF) */
|
||||
/* ddline(DYF) */
|
||||
/* aaline(DYF) */
|
||||
/*0x24*/volatile unsigned int x; /* X triangle(DOXF) */
|
||||
/* aadot(DXF) */
|
||||
/* ddline(DXF) */
|
||||
/* aaline(DXF) */
|
||||
/*0x28*/unsigned int pad2[2]; /* Reserved */
|
||||
/*0x30*/volatile unsigned int ryf; /* Y (alias to DOYF) ddline(RYF) */
|
||||
/* aaline(RYF) */
|
||||
/* triangle(RYF) */
|
||||
/*0x34*/volatile unsigned int rxf; /* X ddline(RXF) */
|
||||
/* aaline(RXF) */
|
||||
/* triangle(RXF) */
|
||||
/*0x38*/unsigned int pad3[2]; /* Reserved */
|
||||
/*0x40*/volatile unsigned int dmyf; /* Y (alias to DOYF) triangle(DMYF) */
|
||||
/*0x44*/volatile unsigned int dmxf; /* X triangle(DMXF) */
|
||||
/*0x48*/unsigned int pad4[2]; /* Reserved */
|
||||
/*0x50*/volatile unsigned int ebyi; /* Y (alias to RYI) polygon(EBYI) */
|
||||
/*0x54*/volatile unsigned int ebxi; /* X polygon(EBXI) */
|
||||
/*0x58*/unsigned int pad5[2]; /* Reserved */
|
||||
/*0x60*/volatile unsigned int by; /* Y brline(RYI) */
|
||||
/* fastfill(OP) */
|
||||
/* polygon(YI) */
|
||||
/* rectangle(YI) */
|
||||
/* bcopy(SRCY) */
|
||||
/* vscroll(SRCY) */
|
||||
/*0x64*/volatile unsigned int bx; /* X brline(RXI) */
|
||||
/* polygon(XI) */
|
||||
/* rectangle(XI) */
|
||||
/* bcopy(SRCX) */
|
||||
/* vscroll(SRCX) */
|
||||
/* fastfill(GO) */
|
||||
/*0x68*/volatile unsigned int dy; /* destination Y fastfill(DSTY) */
|
||||
/* bcopy(DSRY) */
|
||||
/* vscroll(DSRY) */
|
||||
/*0x6c*/volatile unsigned int dx; /* destination X fastfill(DSTX) */
|
||||
/* bcopy(DSTX) */
|
||||
/* vscroll(DSTX) */
|
||||
/*0x70*/volatile unsigned int bh; /* Y (alias to RYI) brline(DYI) */
|
||||
/* dot(DYI) */
|
||||
/* polygon(ETYI) */
|
||||
/* Height fastfill(H) */
|
||||
/* bcopy(H) */
|
||||
/* vscroll(H) */
|
||||
/* Y count fastfill(NY) */
|
||||
/*0x74*/volatile unsigned int bw; /* X dot(DXI) */
|
||||
/* brline(DXI) */
|
||||
/* polygon(ETXI) */
|
||||
/* fastfill(W) */
|
||||
/* bcopy(W) */
|
||||
/* vscroll(W) */
|
||||
/* fastfill(NX) */
|
||||
/*0x78*/unsigned int pad6[2]; /* Reserved */
|
||||
/*0x80*/unsigned int pad7[32]; /* Reserved */
|
||||
|
||||
/* Setup Unit's vertex state register */
|
||||
/*100*/ volatile unsigned int suvtx;
|
||||
/*104*/ unsigned int pad8[63]; /* Reserved */
|
||||
|
||||
/* Frame Buffer Control Registers */
|
||||
/*200*/ volatile unsigned int ppc; /* Pixel Processor Control */
|
||||
/*204*/ volatile unsigned int wid; /* Current WID */
|
||||
/*208*/ volatile unsigned int fg; /* FG data */
|
||||
/*20c*/ volatile unsigned int bg; /* BG data */
|
||||
/*210*/ volatile unsigned int consty; /* Constant Y */
|
||||
/*214*/ volatile unsigned int constz; /* Constant Z */
|
||||
/*218*/ volatile unsigned int xclip; /* X Clip */
|
||||
/*21c*/ volatile unsigned int dcss; /* Depth Cue Scale Slope */
|
||||
/*220*/ volatile unsigned int vclipmin; /* Viewclip XY Min Bounds */
|
||||
/*224*/ volatile unsigned int vclipmax; /* Viewclip XY Max Bounds */
|
||||
/*228*/ volatile unsigned int vclipzmin; /* Viewclip Z Min Bounds */
|
||||
/*22c*/ volatile unsigned int vclipzmax; /* Viewclip Z Max Bounds */
|
||||
/*230*/ volatile unsigned int dcsf; /* Depth Cue Scale Front Bound */
|
||||
/*234*/ volatile unsigned int dcsb; /* Depth Cue Scale Back Bound */
|
||||
/*238*/ volatile unsigned int dczf; /* Depth Cue Z Front */
|
||||
/*23c*/ volatile unsigned int dczb; /* Depth Cue Z Back */
|
||||
/*240*/ unsigned int pad9; /* Reserved */
|
||||
/*244*/ volatile unsigned int blendc; /* Alpha Blend Control */
|
||||
/*248*/ volatile unsigned int blendc1; /* Alpha Blend Color 1 */
|
||||
/*24c*/ volatile unsigned int blendc2; /* Alpha Blend Color 2 */
|
||||
/*250*/ volatile unsigned int fbramitc; /* FB RAM Interleave Test Control */
|
||||
/*254*/ volatile unsigned int fbc; /* Frame Buffer Control */
|
||||
/*258*/ volatile unsigned int rop; /* Raster OPeration */
|
||||
/*25c*/ volatile unsigned int cmp; /* Frame Buffer Compare */
|
||||
/*260*/ volatile unsigned int matchab; /* Buffer AB Match Mask */
|
||||
/*264*/ volatile unsigned int matchc; /* Buffer C(YZ) Match Mask */
|
||||
/*268*/ volatile unsigned int magnab; /* Buffer AB Magnitude Mask */
|
||||
/*26c*/ volatile unsigned int magnc; /* Buffer C(YZ) Magnitude Mask */
|
||||
/*270*/ volatile unsigned int fbcfg0; /* Frame Buffer Config 0 */
|
||||
/*274*/ volatile unsigned int fbcfg1; /* Frame Buffer Config 1 */
|
||||
/*278*/ volatile unsigned int fbcfg2; /* Frame Buffer Config 2 */
|
||||
/*27c*/ volatile unsigned int fbcfg3; /* Frame Buffer Config 3 */
|
||||
/*280*/ volatile unsigned int ppcfg; /* Pixel Processor Config */
|
||||
/*284*/ volatile unsigned int pick; /* Picking Control */
|
||||
/*288*/ volatile unsigned int fillmode; /* FillMode */
|
||||
/*28c*/ volatile unsigned int fbramwac; /* FB RAM Write Address Control */
|
||||
/*290*/ volatile unsigned int pmask; /* RGB PlaneMask */
|
||||
/*294*/ volatile unsigned int xpmask; /* X PlaneMask */
|
||||
/*298*/ volatile unsigned int ypmask; /* Y PlaneMask */
|
||||
/*29c*/ volatile unsigned int zpmask; /* Z PlaneMask */
|
||||
/*2a0*/ ffb_auxclip auxclip[4]; /* Auxilliary Viewport Clip */
|
||||
|
||||
/* New 3dRAM III support regs */
|
||||
/*2c0*/ volatile unsigned int rawblend2;
|
||||
/*2c4*/ volatile unsigned int rawpreblend;
|
||||
/*2c8*/ volatile unsigned int rawstencil;
|
||||
/*2cc*/ volatile unsigned int rawstencilctl;
|
||||
/*2d0*/ volatile unsigned int threedram1;
|
||||
/*2d4*/ volatile unsigned int threedram2;
|
||||
/*2d8*/ volatile unsigned int passin;
|
||||
/*2dc*/ volatile unsigned int rawclrdepth;
|
||||
/*2e0*/ volatile unsigned int rawpmask;
|
||||
/*2e4*/ volatile unsigned int rawcsrc;
|
||||
/*2e8*/ volatile unsigned int rawmatch;
|
||||
/*2ec*/ volatile unsigned int rawmagn;
|
||||
/*2f0*/ volatile unsigned int rawropblend;
|
||||
/*2f4*/ volatile unsigned int rawcmp;
|
||||
/*2f8*/ volatile unsigned int rawwac;
|
||||
/*2fc*/ volatile unsigned int fbramid;
|
||||
|
||||
/*300*/ volatile unsigned int drawop; /* Draw OPeration */
|
||||
/*304*/ unsigned int pad10[2]; /* Reserved */
|
||||
/*30c*/ volatile unsigned int lpat; /* Line Pattern control */
|
||||
/*310*/ unsigned int pad11; /* Reserved */
|
||||
/*314*/ volatile unsigned int fontxy; /* XY Font coordinate */
|
||||
/*318*/ volatile unsigned int fontw; /* Font Width */
|
||||
/*31c*/ volatile unsigned int fontinc; /* Font Increment */
|
||||
/*320*/ volatile unsigned int font; /* Font bits */
|
||||
/*324*/ unsigned int pad12[3]; /* Reserved */
|
||||
/*330*/ volatile unsigned int blend2;
|
||||
/*334*/ volatile unsigned int preblend;
|
||||
/*338*/ volatile unsigned int stencil;
|
||||
/*33c*/ volatile unsigned int stencilctl;
|
||||
*//* DESCRIPTION DRAWOP(NAME) */
|
||||
/*0x00*/ unsigned int pad1[3];
|
||||
/* Reserved */
|
||||
/*0x0c*/ volatile unsigned int alpha;
|
||||
/* ALPHA Transparency */
|
||||
/*0x10*/ volatile unsigned int red;
|
||||
/* RED */
|
||||
/*0x14*/ volatile unsigned int green;
|
||||
/* GREEN */
|
||||
/*0x18*/ volatile unsigned int blue;
|
||||
/* BLUE */
|
||||
/*0x1c*/ volatile unsigned int z;
|
||||
/* DEPTH */
|
||||
/*0x20*/ volatile unsigned int y;
|
||||
/* Y triangle(DOYF) */
|
||||
/* aadot(DYF) */
|
||||
/* ddline(DYF) */
|
||||
/* aaline(DYF) */
|
||||
/*0x24*/ volatile unsigned int x;
|
||||
/* X triangle(DOXF) */
|
||||
/* aadot(DXF) */
|
||||
/* ddline(DXF) */
|
||||
/* aaline(DXF) */
|
||||
/*0x28*/ unsigned int pad2[2];
|
||||
/* Reserved */
|
||||
/*0x30*/ volatile unsigned int ryf;
|
||||
/* Y (alias to DOYF) ddline(RYF) */
|
||||
/* aaline(RYF) */
|
||||
/* triangle(RYF) */
|
||||
/*0x34*/ volatile unsigned int rxf;
|
||||
/* X ddline(RXF) */
|
||||
/* aaline(RXF) */
|
||||
/* triangle(RXF) */
|
||||
/*0x38*/ unsigned int pad3[2];
|
||||
/* Reserved */
|
||||
/*0x40*/ volatile unsigned int dmyf;
|
||||
/* Y (alias to DOYF) triangle(DMYF) */
|
||||
/*0x44*/ volatile unsigned int dmxf;
|
||||
/* X triangle(DMXF) */
|
||||
/*0x48*/ unsigned int pad4[2];
|
||||
/* Reserved */
|
||||
/*0x50*/ volatile unsigned int ebyi;
|
||||
/* Y (alias to RYI) polygon(EBYI) */
|
||||
/*0x54*/ volatile unsigned int ebxi;
|
||||
/* X polygon(EBXI) */
|
||||
/*0x58*/ unsigned int pad5[2];
|
||||
/* Reserved */
|
||||
/*0x60*/ volatile unsigned int by;
|
||||
/* Y brline(RYI) */
|
||||
/* fastfill(OP) */
|
||||
/* polygon(YI) */
|
||||
/* rectangle(YI) */
|
||||
/* bcopy(SRCY) */
|
||||
/* vscroll(SRCY) */
|
||||
/*0x64*/ volatile unsigned int bx;
|
||||
/* X brline(RXI) */
|
||||
/* polygon(XI) */
|
||||
/* rectangle(XI) */
|
||||
/* bcopy(SRCX) */
|
||||
/* vscroll(SRCX) */
|
||||
/* fastfill(GO) */
|
||||
/*0x68*/ volatile unsigned int dy;
|
||||
/* destination Y fastfill(DSTY) */
|
||||
/* bcopy(DSRY) */
|
||||
/* vscroll(DSRY) */
|
||||
/*0x6c*/ volatile unsigned int dx;
|
||||
/* destination X fastfill(DSTX) */
|
||||
/* bcopy(DSTX) */
|
||||
/* vscroll(DSTX) */
|
||||
/*0x70*/ volatile unsigned int bh;
|
||||
/* Y (alias to RYI) brline(DYI) */
|
||||
/* dot(DYI) */
|
||||
/* polygon(ETYI) */
|
||||
/* Height fastfill(H) */
|
||||
/* bcopy(H) */
|
||||
/* vscroll(H) */
|
||||
/* Y count fastfill(NY) */
|
||||
/*0x74*/ volatile unsigned int bw;
|
||||
/* X dot(DXI) */
|
||||
/* brline(DXI) */
|
||||
/* polygon(ETXI) */
|
||||
/* fastfill(W) */
|
||||
/* bcopy(W) */
|
||||
/* vscroll(W) */
|
||||
/* fastfill(NX) */
|
||||
/*0x78*/ unsigned int pad6[2];
|
||||
/* Reserved */
|
||||
/*0x80*/ unsigned int pad7[32];
|
||||
/* Reserved */
|
||||
|
||||
/*340*/ unsigned int pad13[4]; /* Reserved */
|
||||
/*350*/ volatile unsigned int dcss1; /* Depth Cue Scale Slope 1 */
|
||||
/*354*/ volatile unsigned int dcss2; /* Depth Cue Scale Slope 2 */
|
||||
/*358*/ volatile unsigned int dcss3; /* Depth Cue Scale Slope 3 */
|
||||
/*35c*/ volatile unsigned int widpmask;
|
||||
/*360*/ volatile unsigned int dcs2;
|
||||
/*364*/ volatile unsigned int dcs3;
|
||||
/*368*/ volatile unsigned int dcs4;
|
||||
/*36c*/ unsigned int pad14; /* Reserved */
|
||||
/*370*/ volatile unsigned int dcd2;
|
||||
/*374*/ volatile unsigned int dcd3;
|
||||
/*378*/ volatile unsigned int dcd4;
|
||||
/*37c*/ unsigned int pad15; /* Reserved */
|
||||
/*380*/ volatile unsigned int pattern[32]; /* area Pattern */
|
||||
/*400*/ unsigned int pad16[8]; /* Reserved */
|
||||
/*420*/ volatile unsigned int reset; /* chip RESET */
|
||||
/*424*/ unsigned int pad17[247]; /* Reserved */
|
||||
/*800*/ volatile unsigned int devid; /* Device ID */
|
||||
/*804*/ unsigned int pad18[63]; /* Reserved */
|
||||
/*900*/ volatile unsigned int ucsr; /* User Control & Status Register */
|
||||
/*904*/ unsigned int pad19[31]; /* Reserved */
|
||||
/*980*/ volatile unsigned int mer; /* Mode Enable Register */
|
||||
/*984*/ unsigned int pad20[1439]; /* Reserved */
|
||||
/* Setup Unit's vertex state register */
|
||||
/*100*/ volatile unsigned int suvtx;
|
||||
/*104*/ unsigned int pad8[63];
|
||||
/* Reserved */
|
||||
|
||||
/* Frame Buffer Control Registers */
|
||||
/*200*/ volatile unsigned int ppc;
|
||||
/* Pixel Processor Control */
|
||||
/*204*/ volatile unsigned int wid;
|
||||
/* Current WID */
|
||||
/*208*/ volatile unsigned int fg;
|
||||
/* FG data */
|
||||
/*20c*/ volatile unsigned int bg;
|
||||
/* BG data */
|
||||
/*210*/ volatile unsigned int consty;
|
||||
/* Constant Y */
|
||||
/*214*/ volatile unsigned int constz;
|
||||
/* Constant Z */
|
||||
/*218*/ volatile unsigned int xclip;
|
||||
/* X Clip */
|
||||
/*21c*/ volatile unsigned int dcss;
|
||||
/* Depth Cue Scale Slope */
|
||||
/*220*/ volatile unsigned int vclipmin;
|
||||
/* Viewclip XY Min Bounds */
|
||||
/*224*/ volatile unsigned int vclipmax;
|
||||
/* Viewclip XY Max Bounds */
|
||||
/*228*/ volatile unsigned int vclipzmin;
|
||||
/* Viewclip Z Min Bounds */
|
||||
/*22c*/ volatile unsigned int vclipzmax;
|
||||
/* Viewclip Z Max Bounds */
|
||||
/*230*/ volatile unsigned int dcsf;
|
||||
/* Depth Cue Scale Front Bound */
|
||||
/*234*/ volatile unsigned int dcsb;
|
||||
/* Depth Cue Scale Back Bound */
|
||||
/*238*/ volatile unsigned int dczf;
|
||||
/* Depth Cue Z Front */
|
||||
/*23c*/ volatile unsigned int dczb;
|
||||
/* Depth Cue Z Back */
|
||||
/*240*/ unsigned int pad9;
|
||||
/* Reserved */
|
||||
/*244*/ volatile unsigned int blendc;
|
||||
/* Alpha Blend Control */
|
||||
/*248*/ volatile unsigned int blendc1;
|
||||
/* Alpha Blend Color 1 */
|
||||
/*24c*/ volatile unsigned int blendc2;
|
||||
/* Alpha Blend Color 2 */
|
||||
/*250*/ volatile unsigned int fbramitc;
|
||||
/* FB RAM Interleave Test Control */
|
||||
/*254*/ volatile unsigned int fbc;
|
||||
/* Frame Buffer Control */
|
||||
/*258*/ volatile unsigned int rop;
|
||||
/* Raster OPeration */
|
||||
/*25c*/ volatile unsigned int cmp;
|
||||
/* Frame Buffer Compare */
|
||||
/*260*/ volatile unsigned int matchab;
|
||||
/* Buffer AB Match Mask */
|
||||
/*264*/ volatile unsigned int matchc;
|
||||
/* Buffer C(YZ) Match Mask */
|
||||
/*268*/ volatile unsigned int magnab;
|
||||
/* Buffer AB Magnitude Mask */
|
||||
/*26c*/ volatile unsigned int magnc;
|
||||
/* Buffer C(YZ) Magnitude Mask */
|
||||
/*270*/ volatile unsigned int fbcfg0;
|
||||
/* Frame Buffer Config 0 */
|
||||
/*274*/ volatile unsigned int fbcfg1;
|
||||
/* Frame Buffer Config 1 */
|
||||
/*278*/ volatile unsigned int fbcfg2;
|
||||
/* Frame Buffer Config 2 */
|
||||
/*27c*/ volatile unsigned int fbcfg3;
|
||||
/* Frame Buffer Config 3 */
|
||||
/*280*/ volatile unsigned int ppcfg;
|
||||
/* Pixel Processor Config */
|
||||
/*284*/ volatile unsigned int pick;
|
||||
/* Picking Control */
|
||||
/*288*/ volatile unsigned int fillmode;
|
||||
/* FillMode */
|
||||
/*28c*/ volatile unsigned int fbramwac;
|
||||
/* FB RAM Write Address Control */
|
||||
/*290*/ volatile unsigned int pmask;
|
||||
/* RGB PlaneMask */
|
||||
/*294*/ volatile unsigned int xpmask;
|
||||
/* X PlaneMask */
|
||||
/*298*/ volatile unsigned int ypmask;
|
||||
/* Y PlaneMask */
|
||||
/*29c*/ volatile unsigned int zpmask;
|
||||
/* Z PlaneMask */
|
||||
/*2a0*/ ffb_auxclip auxclip[4];
|
||||
/* Auxilliary Viewport Clip */
|
||||
|
||||
/* New 3dRAM III support regs */
|
||||
/*2c0*/ volatile unsigned int rawblend2;
|
||||
/*2c4*/ volatile unsigned int rawpreblend;
|
||||
/*2c8*/ volatile unsigned int rawstencil;
|
||||
/*2cc*/ volatile unsigned int rawstencilctl;
|
||||
/*2d0*/ volatile unsigned int threedram1;
|
||||
/*2d4*/ volatile unsigned int threedram2;
|
||||
/*2d8*/ volatile unsigned int passin;
|
||||
/*2dc*/ volatile unsigned int rawclrdepth;
|
||||
/*2e0*/ volatile unsigned int rawpmask;
|
||||
/*2e4*/ volatile unsigned int rawcsrc;
|
||||
/*2e8*/ volatile unsigned int rawmatch;
|
||||
/*2ec*/ volatile unsigned int rawmagn;
|
||||
/*2f0*/ volatile unsigned int rawropblend;
|
||||
/*2f4*/ volatile unsigned int rawcmp;
|
||||
/*2f8*/ volatile unsigned int rawwac;
|
||||
/*2fc*/ volatile unsigned int fbramid;
|
||||
|
||||
/*300*/ volatile unsigned int drawop;
|
||||
/* Draw OPeration */
|
||||
/*304*/ unsigned int pad10[2];
|
||||
/* Reserved */
|
||||
/*30c*/ volatile unsigned int lpat;
|
||||
/* Line Pattern control */
|
||||
/*310*/ unsigned int pad11;
|
||||
/* Reserved */
|
||||
/*314*/ volatile unsigned int fontxy;
|
||||
/* XY Font coordinate */
|
||||
/*318*/ volatile unsigned int fontw;
|
||||
/* Font Width */
|
||||
/*31c*/ volatile unsigned int fontinc;
|
||||
/* Font Increment */
|
||||
/*320*/ volatile unsigned int font;
|
||||
/* Font bits */
|
||||
/*324*/ unsigned int pad12[3];
|
||||
/* Reserved */
|
||||
/*330*/ volatile unsigned int blend2;
|
||||
/*334*/ volatile unsigned int preblend;
|
||||
/*338*/ volatile unsigned int stencil;
|
||||
/*33c*/ volatile unsigned int stencilctl;
|
||||
|
||||
/*340*/ unsigned int pad13[4];
|
||||
/* Reserved */
|
||||
/*350*/ volatile unsigned int dcss1;
|
||||
/* Depth Cue Scale Slope 1 */
|
||||
/*354*/ volatile unsigned int dcss2;
|
||||
/* Depth Cue Scale Slope 2 */
|
||||
/*358*/ volatile unsigned int dcss3;
|
||||
/* Depth Cue Scale Slope 3 */
|
||||
/*35c*/ volatile unsigned int widpmask;
|
||||
/*360*/ volatile unsigned int dcs2;
|
||||
/*364*/ volatile unsigned int dcs3;
|
||||
/*368*/ volatile unsigned int dcs4;
|
||||
/*36c*/ unsigned int pad14;
|
||||
/* Reserved */
|
||||
/*370*/ volatile unsigned int dcd2;
|
||||
/*374*/ volatile unsigned int dcd3;
|
||||
/*378*/ volatile unsigned int dcd4;
|
||||
/*37c*/ unsigned int pad15;
|
||||
/* Reserved */
|
||||
/*380*/ volatile unsigned int pattern[32];
|
||||
/* area Pattern */
|
||||
/*400*/ unsigned int pad16[8];
|
||||
/* Reserved */
|
||||
/*420*/ volatile unsigned int reset;
|
||||
/* chip RESET */
|
||||
/*424*/ unsigned int pad17[247];
|
||||
/* Reserved */
|
||||
/*800*/ volatile unsigned int devid;
|
||||
/* Device ID */
|
||||
/*804*/ unsigned int pad18[63];
|
||||
/* Reserved */
|
||||
/*900*/ volatile unsigned int ucsr;
|
||||
/* User Control & Status Register */
|
||||
/*904*/ unsigned int pad19[31];
|
||||
/* Reserved */
|
||||
/*980*/ volatile unsigned int mer;
|
||||
/* Mode Enable Register */
|
||||
/*984*/ unsigned int pad20[1439];
|
||||
/* Reserved */
|
||||
} ffb_fbc, *ffb_fbcPtr;
|
||||
|
||||
struct ffb_hw_context {
|
||||
|
@ -263,16 +356,16 @@ enum ffb_chip_type {
|
|||
|
||||
typedef struct ffb_dev_priv {
|
||||
/* Misc software state. */
|
||||
int prom_node;
|
||||
enum ffb_chip_type ffb_type;
|
||||
u64 card_phys_base;
|
||||
struct miscdevice miscdev;
|
||||
int prom_node;
|
||||
enum ffb_chip_type ffb_type;
|
||||
u64 card_phys_base;
|
||||
struct miscdevice miscdev;
|
||||
|
||||
/* Controller registers. */
|
||||
ffb_fbcPtr regs;
|
||||
ffb_fbcPtr regs;
|
||||
|
||||
/* Context table. */
|
||||
struct ffb_hw_context *hw_state[FFB_MAX_CTXS];
|
||||
struct ffb_hw_context *hw_state[FFB_MAX_CTXS];
|
||||
} ffb_dev_priv_t;
|
||||
|
||||
extern unsigned long ffb_get_unmapped_area(struct file *filp,
|
||||
|
@ -283,4 +376,4 @@ extern unsigned long ffb_get_unmapped_area(struct file *filp,
|
|||
extern void ffb_set_context_ioctls(void);
|
||||
extern drm_ioctl_desc_t DRM(ioctls)[];
|
||||
|
||||
extern int ffb_driver_context_switch(drm_device_t *dev, int old, int new);
|
||||
extern int ffb_driver_context_switch(drm_device_t * dev, int old, int new);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,21 +19,20 @@
|
|||
#define I810_LOG_MIN_TEX_REGION_SIZE 16
|
||||
#endif
|
||||
|
||||
#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
|
||||
#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
|
||||
#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
|
||||
#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
|
||||
#define I810_UPLOAD_CTX 0x4
|
||||
#define I810_UPLOAD_BUFFERS 0x8
|
||||
#define I810_UPLOAD_TEX0 0x10
|
||||
#define I810_UPLOAD_TEX1 0x20
|
||||
#define I810_UPLOAD_CLIPRECTS 0x40
|
||||
|
||||
|
||||
/* Indices into buf.Setup where various bits of state are mirrored per
|
||||
* context and per buffer. These can be fired at the card as a unit,
|
||||
* or in a piecewise fashion as required.
|
||||
*/
|
||||
|
||||
/* Destbuffer state
|
||||
/* Destbuffer state
|
||||
* - backbuffer linear offset and pitch -- invarient in the current dri
|
||||
* - zbuffer linear offset and pitch -- also invarient
|
||||
* - drawing origin in back and depth buffers.
|
||||
|
@ -55,13 +54,13 @@
|
|||
/* Context state
|
||||
*/
|
||||
#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */
|
||||
#define I810_CTXREG_CF1 1
|
||||
#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
|
||||
#define I810_CTXREG_CF1 1
|
||||
#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
|
||||
#define I810_CTXREG_ST1 3
|
||||
#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */
|
||||
#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */
|
||||
#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
|
||||
#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
|
||||
#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
|
||||
#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
|
||||
#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
|
||||
#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
|
||||
|
@ -74,14 +73,14 @@
|
|||
#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */
|
||||
#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */
|
||||
#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */
|
||||
#define I810_CTX_SETUP_SIZE 20
|
||||
#define I810_CTX_SETUP_SIZE 20
|
||||
|
||||
/* Texture state (per tex unit)
|
||||
*/
|
||||
#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */
|
||||
#define I810_TEXREG_MI1 1
|
||||
#define I810_TEXREG_MI2 2
|
||||
#define I810_TEXREG_MI3 3
|
||||
#define I810_TEXREG_MI1 1
|
||||
#define I810_TEXREG_MI2 2
|
||||
#define I810_TEXREG_MI3 3
|
||||
#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */
|
||||
#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */
|
||||
#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */
|
||||
|
@ -98,7 +97,7 @@ typedef enum _drm_i810_init_func {
|
|||
I810_INIT_DMA = 0x01,
|
||||
I810_CLEANUP_DMA = 0x02,
|
||||
I810_INIT_DMA_1_4 = 0x03
|
||||
} drm_i810_init_func_t;
|
||||
} drm_i810_init_func_t;
|
||||
|
||||
/* This is the init structure after v1.2 */
|
||||
typedef struct _drm_i810_init {
|
||||
|
@ -122,7 +121,7 @@ typedef struct _drm_i810_init {
|
|||
unsigned int w;
|
||||
unsigned int h;
|
||||
unsigned int pitch;
|
||||
unsigned int pitch_bits;
|
||||
unsigned int pitch_bits;
|
||||
} drm_i810_init_t;
|
||||
|
||||
/* This is the init structure prior to v1.2 */
|
||||
|
@ -140,23 +139,23 @@ typedef struct _drm_i810_pre12_init {
|
|||
unsigned int w;
|
||||
unsigned int h;
|
||||
unsigned int pitch;
|
||||
unsigned int pitch_bits;
|
||||
unsigned int pitch_bits;
|
||||
} drm_i810_pre12_init_t;
|
||||
|
||||
/* Warning: If you change the SAREA structure you must change the Xserver
|
||||
* structure as well */
|
||||
|
||||
typedef struct _drm_i810_tex_region {
|
||||
unsigned char next, prev; /* indices to form a circular LRU */
|
||||
unsigned char next, prev; /* indices to form a circular LRU */
|
||||
unsigned char in_use; /* owned by a client, or free? */
|
||||
int age; /* tracked by clients to update local LRU's */
|
||||
} drm_i810_tex_region_t;
|
||||
|
||||
typedef struct _drm_i810_sarea {
|
||||
unsigned int ContextState[I810_CTX_SETUP_SIZE];
|
||||
unsigned int BufferState[I810_DEST_SETUP_SIZE];
|
||||
unsigned int TexState[2][I810_TEX_SETUP_SIZE];
|
||||
unsigned int dirty;
|
||||
unsigned int ContextState[I810_CTX_SETUP_SIZE];
|
||||
unsigned int BufferState[I810_DEST_SETUP_SIZE];
|
||||
unsigned int TexState[2][I810_TEX_SETUP_SIZE];
|
||||
unsigned int dirty;
|
||||
|
||||
unsigned int nbox;
|
||||
drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
|
||||
|
@ -174,22 +173,22 @@ typedef struct _drm_i810_sarea {
|
|||
* texture space, and can make informed decisions as to which
|
||||
* areas to kick out. There is no need to choose whether to
|
||||
* kick out your own texture or someone else's - simply eject
|
||||
* them all in LRU order.
|
||||
* them all in LRU order.
|
||||
*/
|
||||
|
||||
drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS+1];
|
||||
/* Last elt is sentinal */
|
||||
int texAge; /* last time texture was uploaded */
|
||||
int last_enqueue; /* last time a buffer was enqueued */
|
||||
|
||||
drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS + 1];
|
||||
/* Last elt is sentinal */
|
||||
int texAge; /* last time texture was uploaded */
|
||||
int last_enqueue; /* last time a buffer was enqueued */
|
||||
int last_dispatch; /* age of the most recently dispatched buffer */
|
||||
int last_quiescent; /* */
|
||||
int last_quiescent; /* */
|
||||
int ctxOwner; /* last context to upload state */
|
||||
|
||||
int vertex_prim;
|
||||
|
||||
int pf_enabled; /* is pageflipping allowed? */
|
||||
int pf_enabled; /* is pageflipping allowed? */
|
||||
int pf_active;
|
||||
int pf_current_page; /* which buffer is being displayed? */
|
||||
int pf_current_page; /* which buffer is being displayed? */
|
||||
} drm_i810_sarea_t;
|
||||
|
||||
/* WARNING: If you change any of these defines, make sure to change the
|
||||
|
@ -243,13 +242,13 @@ typedef struct _drm_i810_clear {
|
|||
* new set of cliprects.
|
||||
*/
|
||||
typedef struct _drm_i810_vertex {
|
||||
int idx; /* buffer index */
|
||||
int idx; /* buffer index */
|
||||
int used; /* nr bytes in use */
|
||||
int discard; /* client is finished with the buffer? */
|
||||
} drm_i810_vertex_t;
|
||||
|
||||
typedef struct _drm_i810_copy_t {
|
||||
int idx; /* buffer index */
|
||||
int idx; /* buffer index */
|
||||
int used; /* nr bytes in use */
|
||||
void *address; /* Address to copy from */
|
||||
} drm_i810_copy_t;
|
||||
|
@ -264,7 +263,6 @@ typedef struct _drm_i810_copy_t {
|
|||
#define PR_RECTS (0x7<<18)
|
||||
#define PR_MASK (0x7<<18)
|
||||
|
||||
|
||||
typedef struct drm_i810_dma {
|
||||
void *virtual;
|
||||
int request_idx;
|
||||
|
@ -273,17 +271,16 @@ typedef struct drm_i810_dma {
|
|||
} drm_i810_dma_t;
|
||||
|
||||
typedef struct _drm_i810_overlay_t {
|
||||
unsigned int offset; /* Address of the Overlay Regs */
|
||||
unsigned int offset; /* Address of the Overlay Regs */
|
||||
unsigned int physical;
|
||||
} drm_i810_overlay_t;
|
||||
|
||||
typedef struct _drm_i810_mc {
|
||||
int idx; /* buffer index */
|
||||
int used; /* nr bytes in use */
|
||||
int num_blocks; /* number of GFXBlocks */
|
||||
int *length; /* List of lengths for GFXBlocks (FUTURE)*/
|
||||
unsigned int last_render; /* Last Render Request */
|
||||
int idx; /* buffer index */
|
||||
int used; /* nr bytes in use */
|
||||
int num_blocks; /* number of GFXBlocks */
|
||||
int *length; /* List of lengths for GFXBlocks (FUTURE) */
|
||||
unsigned int last_render; /* Last Render Request */
|
||||
} drm_i810_mc_t;
|
||||
|
||||
|
||||
#endif /* _I810_DRM_H_ */
|
||||
#endif /* _I810_DRM_H_ */
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include "drm_pciids.h"
|
||||
|
||||
static int postinit( struct drm_device *dev, unsigned long flags )
|
||||
static int postinit(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
/* i810 has 4 more counters */
|
||||
dev->counters += 4;
|
||||
|
@ -46,29 +46,27 @@ static int postinit( struct drm_device *dev, unsigned long flags )
|
|||
dev->types[7] = _DRM_STAT_PRIMARY;
|
||||
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||
dev->types[9] = _DRM_STAT_DMA;
|
||||
|
||||
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE,
|
||||
dev->primary.minor,
|
||||
pci_pretty_name(dev->pdev)
|
||||
);
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int version( drm_version_t *version )
|
||||
static int version(drm_version_t * version)
|
||||
{
|
||||
int len;
|
||||
|
||||
version->version_major = DRIVER_MAJOR;
|
||||
version->version_minor = DRIVER_MINOR;
|
||||
version->version_patchlevel = DRIVER_PATCHLEVEL;
|
||||
DRM_COPY( version->name, DRIVER_NAME );
|
||||
DRM_COPY( version->date, DRIVER_DATE );
|
||||
DRM_COPY( version->desc, DRIVER_DESC );
|
||||
DRM_COPY(version->name, DRIVER_NAME);
|
||||
DRM_COPY(version->date, DRIVER_DATE);
|
||||
DRM_COPY(version->desc, DRIVER_DESC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -76,11 +74,10 @@ static struct pci_device_id pciidlist[] = {
|
|||
i810_PCI_IDS
|
||||
};
|
||||
|
||||
extern drm_ioctl_desc_t i810_ioctls[];
|
||||
extern int i810_max_ioctl;
|
||||
|
||||
static struct drm_driver driver = {
|
||||
.driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
|
||||
DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
|
||||
.dev_priv_size = sizeof(drm_i810_buf_priv_t),
|
||||
.pretakedown = i810_driver_pretakedown,
|
||||
.prerelease = i810_driver_prerelease,
|
||||
|
@ -94,18 +91,20 @@ static struct drm_driver driver = {
|
|||
.version = version,
|
||||
.ioctls = i810_ioctls,
|
||||
.fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
},
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
}
|
||||
,
|
||||
.pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
},
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
}
|
||||
,
|
||||
};
|
||||
|
||||
static int __init i810_init(void)
|
||||
|
@ -122,6 +121,6 @@ static void __exit i810_exit(void)
|
|||
module_init(i810_init);
|
||||
module_exit(i810_exit);
|
||||
|
||||
MODULE_AUTHOR( DRIVER_AUTHOR );
|
||||
MODULE_DESCRIPTION( DRIVER_DESC );
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
|
|
@ -56,14 +56,14 @@
|
|||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
typedef struct drm_i810_buf_priv {
|
||||
u32 *in_use;
|
||||
int my_use_idx;
|
||||
u32 *in_use;
|
||||
int my_use_idx;
|
||||
int currently_mapped;
|
||||
void *virtual;
|
||||
void *kernel_virtual;
|
||||
} drm_i810_buf_priv_t;
|
||||
|
||||
typedef struct _drm_i810_ring_buffer{
|
||||
typedef struct _drm_i810_ring_buffer {
|
||||
int tail_mask;
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
|
@ -79,16 +79,15 @@ typedef struct drm_i810_private {
|
|||
drm_map_t *mmio_map;
|
||||
|
||||
drm_i810_sarea_t *sarea_priv;
|
||||
drm_i810_ring_buffer_t ring;
|
||||
drm_i810_ring_buffer_t ring;
|
||||
|
||||
void *hw_status_page;
|
||||
unsigned long counter;
|
||||
void *hw_status_page;
|
||||
unsigned long counter;
|
||||
|
||||
dma_addr_t dma_status_page;
|
||||
|
||||
drm_buf_t *mmap_buffer;
|
||||
|
||||
|
||||
u32 front_di1, back_di1, zi1;
|
||||
|
||||
int back_offset;
|
||||
|
@ -97,7 +96,7 @@ typedef struct drm_i810_private {
|
|||
int overlay_physical;
|
||||
int w, h;
|
||||
int pitch;
|
||||
int back_pitch;
|
||||
int back_pitch;
|
||||
int depth_pitch;
|
||||
|
||||
int do_boxes;
|
||||
|
@ -107,21 +106,24 @@ typedef struct drm_i810_private {
|
|||
int page_flipping;
|
||||
|
||||
wait_queue_head_t irq_queue;
|
||||
atomic_t irq_received;
|
||||
atomic_t irq_emitted;
|
||||
|
||||
int front_offset;
|
||||
atomic_t irq_received;
|
||||
atomic_t irq_emitted;
|
||||
|
||||
int front_offset;
|
||||
} drm_i810_private_t;
|
||||
|
||||
/* i810_dma.c */
|
||||
extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp);
|
||||
extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp);
|
||||
|
||||
extern int i810_driver_dma_quiescent(drm_device_t *dev);
|
||||
extern void i810_driver_release(drm_device_t *dev, struct file *filp);
|
||||
extern void i810_driver_pretakedown(drm_device_t *dev);
|
||||
extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
|
||||
extern int i810_driver_dma_quiescent(drm_device_t * dev);
|
||||
extern void i810_driver_release(drm_device_t * dev, struct file *filp);
|
||||
extern void i810_driver_pretakedown(drm_device_t * dev);
|
||||
extern void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp);
|
||||
extern int i810_driver_device_is_agp(drm_device_t * dev);
|
||||
|
||||
extern drm_ioctl_desc_t i810_ioctls[];
|
||||
extern int i810_max_ioctl;
|
||||
|
||||
#define I810_BASE(reg) ((unsigned long) \
|
||||
dev_priv->mmio_map->handle)
|
||||
#define I810_ADDR(reg) (I810_BASE(reg) + reg)
|
||||
|
@ -170,7 +172,6 @@ extern int i810_driver_device_is_agp(drm_device_t * dev);
|
|||
#define INST_OP_FLUSH 0x02000000
|
||||
#define INST_FLUSH_MAP_CACHE 0x00000001
|
||||
|
||||
|
||||
#define BB1_START_ADDR_MASK (~0x7)
|
||||
#define BB1_PROTECTED (1<<0)
|
||||
#define BB1_UNPROTECTED (0<<0)
|
||||
|
@ -229,8 +230,8 @@ extern int i810_driver_device_is_agp(drm_device_t * dev);
|
|||
#define BR00_OP_SRC_COPY_BLT 0x10C00000
|
||||
#define BR13_SOLID_PATTERN 0x80000000
|
||||
|
||||
#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
|
||||
#define WAIT_FOR_PLANE_A_FLIP (1<<2)
|
||||
#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
|
||||
#define WAIT_FOR_PLANE_A_FLIP (1<<2)
|
||||
#define WAIT_FOR_VBLANK (1<<3)
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,14 +33,14 @@
|
|||
#define I830_UPLOAD_CTX 0x1
|
||||
#define I830_UPLOAD_BUFFERS 0x2
|
||||
#define I830_UPLOAD_CLIPRECTS 0x4
|
||||
#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */
|
||||
#define I830_UPLOAD_TEX_N_IMAGE(n) (0x100 << (n * 2))
|
||||
#define I830_UPLOAD_TEX_N_CUBE(n) (0x200 << (n * 2))
|
||||
#define I830_UPLOAD_TEXIMAGE_MASK 0xff00
|
||||
|
@ -65,7 +65,7 @@
|
|||
* or in a piecewise fashion as required.
|
||||
*/
|
||||
|
||||
/* Destbuffer state
|
||||
/* Destbuffer state
|
||||
* - backbuffer linear offset and pitch -- invarient in the current dri
|
||||
* - zbuffer linear offset and pitch -- also invarient
|
||||
* - drawing origin in back and depth buffers.
|
||||
|
@ -103,7 +103,7 @@
|
|||
#define I830_CTXREG_AA 9
|
||||
#define I830_CTXREG_FOGCOLOR 10
|
||||
#define I830_CTXREG_BLENDCOLR0 11
|
||||
#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */
|
||||
#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */
|
||||
#define I830_CTXREG_VF 13
|
||||
#define I830_CTXREG_VF2 14
|
||||
#define I830_CTXREG_MCSB0 15
|
||||
|
@ -111,12 +111,11 @@
|
|||
#define I830_CTX_SETUP_SIZE 17
|
||||
|
||||
/* 1.3: Stipple state
|
||||
*/
|
||||
*/
|
||||
#define I830_STPREG_ST0 0
|
||||
#define I830_STPREG_ST1 1
|
||||
#define I830_STP_SETUP_SIZE 2
|
||||
|
||||
|
||||
/* Texture state (per tex unit)
|
||||
*/
|
||||
|
||||
|
@ -132,23 +131,23 @@
|
|||
#define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */
|
||||
#define I830_TEX_SETUP_SIZE 10
|
||||
|
||||
#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
|
||||
#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
|
||||
#define I830_TEXREG_TM0S0 1
|
||||
#define I830_TEXREG_TM0S1 2
|
||||
#define I830_TEXREG_TM0S2 3
|
||||
#define I830_TEXREG_TM0S3 4
|
||||
#define I830_TEXREG_TM0S4 5
|
||||
#define I830_TEXREG_NOP0 6 /* noop */
|
||||
#define I830_TEXREG_NOP1 7 /* noop */
|
||||
#define I830_TEXREG_NOP2 8 /* noop */
|
||||
#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
|
||||
#define I830_TEXREG_NOP0 6 /* noop */
|
||||
#define I830_TEXREG_NOP1 7 /* noop */
|
||||
#define I830_TEXREG_NOP2 8 /* noop */
|
||||
#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */
|
||||
#define __I830_TEX_SETUP_SIZE 10
|
||||
|
||||
#define I830_FRONT 0x1
|
||||
#define I830_BACK 0x2
|
||||
#define I830_DEPTH 0x4
|
||||
|
||||
#endif /* _I830_DEFINES_ */
|
||||
#endif /* _I830_DEFINES_ */
|
||||
|
||||
typedef struct _drm_i830_init {
|
||||
enum {
|
||||
|
@ -177,19 +176,19 @@ typedef struct _drm_i830_init {
|
|||
* structure as well */
|
||||
|
||||
typedef struct _drm_i830_tex_region {
|
||||
unsigned char next, prev; /* indices to form a circular LRU */
|
||||
unsigned char next, prev; /* indices to form a circular LRU */
|
||||
unsigned char in_use; /* owned by a client, or free? */
|
||||
int age; /* tracked by clients to update local LRU's */
|
||||
} drm_i830_tex_region_t;
|
||||
|
||||
typedef struct _drm_i830_sarea {
|
||||
unsigned int ContextState[I830_CTX_SETUP_SIZE];
|
||||
unsigned int BufferState[I830_DEST_SETUP_SIZE];
|
||||
unsigned int BufferState[I830_DEST_SETUP_SIZE];
|
||||
unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
|
||||
unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
|
||||
unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
|
||||
unsigned int Palette[2][256];
|
||||
unsigned int dirty;
|
||||
unsigned int dirty;
|
||||
|
||||
unsigned int nbox;
|
||||
drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS];
|
||||
|
@ -207,26 +206,26 @@ typedef struct _drm_i830_sarea {
|
|||
* texture space, and can make informed decisions as to which
|
||||
* areas to kick out. There is no need to choose whether to
|
||||
* kick out your own texture or someone else's - simply eject
|
||||
* them all in LRU order.
|
||||
* them all in LRU order.
|
||||
*/
|
||||
|
||||
drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS+1];
|
||||
/* Last elt is sentinal */
|
||||
int texAge; /* last time texture was uploaded */
|
||||
int last_enqueue; /* last time a buffer was enqueued */
|
||||
drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS + 1];
|
||||
/* Last elt is sentinal */
|
||||
int texAge; /* last time texture was uploaded */
|
||||
int last_enqueue; /* last time a buffer was enqueued */
|
||||
int last_dispatch; /* age of the most recently dispatched buffer */
|
||||
int last_quiescent; /* */
|
||||
int last_quiescent; /* */
|
||||
int ctxOwner; /* last context to upload state */
|
||||
|
||||
int vertex_prim;
|
||||
|
||||
int pf_enabled; /* is pageflipping allowed? */
|
||||
int pf_active;
|
||||
int pf_current_page; /* which buffer is being displayed? */
|
||||
int pf_enabled; /* is pageflipping allowed? */
|
||||
int pf_active;
|
||||
int pf_current_page; /* which buffer is being displayed? */
|
||||
|
||||
int perf_boxes; /* performance boxes to be displayed */
|
||||
|
||||
/* Here's the state for texunits 2,3:
|
||||
int perf_boxes; /* performance boxes to be displayed */
|
||||
|
||||
/* Here's the state for texunits 2,3:
|
||||
*/
|
||||
unsigned int TexState2[I830_TEX_SETUP_SIZE];
|
||||
unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
|
||||
|
@ -241,12 +240,11 @@ typedef struct _drm_i830_sarea {
|
|||
|
||||
/* Flags for perf_boxes
|
||||
*/
|
||||
#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
|
||||
#define I830_BOX_FLIP 0x2 /* populated by kernel */
|
||||
#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
|
||||
#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
|
||||
#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
|
||||
|
||||
#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */
|
||||
#define I830_BOX_FLIP 0x2 /* populated by kernel */
|
||||
#define I830_BOX_WAIT 0x4 /* populated by kernel & client */
|
||||
#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */
|
||||
#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */
|
||||
|
||||
/* I830 specific ioctls
|
||||
* The device specific ioctl range is 0x40 to 0x79.
|
||||
|
@ -289,23 +287,21 @@ typedef struct _drm_i830_clear {
|
|||
unsigned int clear_depthmask;
|
||||
} drm_i830_clear_t;
|
||||
|
||||
|
||||
|
||||
/* These may be placeholders if we have more cliprects than
|
||||
* I830_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
|
||||
* false, indicating that the buffer will be dispatched again with a
|
||||
* new set of cliprects.
|
||||
*/
|
||||
typedef struct _drm_i830_vertex {
|
||||
int idx; /* buffer index */
|
||||
int idx; /* buffer index */
|
||||
int used; /* nr bytes in use */
|
||||
int discard; /* client is finished with the buffer? */
|
||||
} drm_i830_vertex_t;
|
||||
|
||||
typedef struct _drm_i830_copy_t {
|
||||
int idx; /* buffer index */
|
||||
int idx; /* buffer index */
|
||||
int used; /* nr bytes in use */
|
||||
void __user *address; /* Address to copy from */
|
||||
void __user *address; /* Address to copy from */
|
||||
} drm_i830_copy_t;
|
||||
|
||||
typedef struct drm_i830_dma {
|
||||
|
@ -315,7 +311,6 @@ typedef struct drm_i830_dma {
|
|||
int granted;
|
||||
} drm_i830_dma_t;
|
||||
|
||||
|
||||
/* 1.3: Userspace can request & wait on irq's:
|
||||
*/
|
||||
typedef struct drm_i830_irq_emit {
|
||||
|
@ -326,7 +321,6 @@ typedef struct drm_i830_irq_wait {
|
|||
int irq_seq;
|
||||
} drm_i830_irq_wait_t;
|
||||
|
||||
|
||||
/* 1.3: New ioctl to query kernel params:
|
||||
*/
|
||||
#define I830_PARAM_IRQ_ACTIVE 1
|
||||
|
@ -336,7 +330,6 @@ typedef struct drm_i830_getparam {
|
|||
int __user *value;
|
||||
} drm_i830_getparam_t;
|
||||
|
||||
|
||||
/* 1.3: New ioctl to set kernel params:
|
||||
*/
|
||||
#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1
|
||||
|
@ -346,5 +339,4 @@ typedef struct drm_i830_setparam {
|
|||
int value;
|
||||
} drm_i830_setparam_t;
|
||||
|
||||
|
||||
#endif /* _I830_DRM_H_ */
|
||||
#endif /* _I830_DRM_H_ */
|
||||
|
|
|
@ -40,36 +40,34 @@
|
|||
|
||||
#include "drm_pciids.h"
|
||||
|
||||
static int postinit( struct drm_device *dev, unsigned long flags )
|
||||
static int postinit(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
dev->counters += 4;
|
||||
dev->types[6] = _DRM_STAT_IRQ;
|
||||
dev->types[7] = _DRM_STAT_PRIMARY;
|
||||
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||
dev->types[9] = _DRM_STAT_DMA;
|
||||
|
||||
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE,
|
||||
dev->primary.minor,
|
||||
pci_pretty_name(dev->pdev)
|
||||
);
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int version( drm_version_t *version )
|
||||
static int version(drm_version_t * version)
|
||||
{
|
||||
int len;
|
||||
|
||||
version->version_major = DRIVER_MAJOR;
|
||||
version->version_minor = DRIVER_MINOR;
|
||||
version->version_patchlevel = DRIVER_PATCHLEVEL;
|
||||
DRM_COPY( version->name, DRIVER_NAME );
|
||||
DRM_COPY( version->date, DRIVER_DATE );
|
||||
DRM_COPY( version->desc, DRIVER_DESC );
|
||||
DRM_COPY(version->name, DRIVER_NAME);
|
||||
DRM_COPY(version->date, DRIVER_DATE);
|
||||
DRM_COPY(version->desc, DRIVER_DESC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -77,11 +75,10 @@ static struct pci_device_id pciidlist[] = {
|
|||
i830_PCI_IDS
|
||||
};
|
||||
|
||||
extern drm_ioctl_desc_t i830_ioctls[];
|
||||
extern int i830_max_ioctl;
|
||||
|
||||
static struct drm_driver driver = {
|
||||
.driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
|
||||
DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
|
||||
#if USE_IRQS
|
||||
.driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
|
||||
#endif
|
||||
|
@ -104,18 +101,19 @@ static struct drm_driver driver = {
|
|||
.version = version,
|
||||
.ioctls = i830_ioctls,
|
||||
.fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
},
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
}
|
||||
,
|
||||
.pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
}
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -133,6 +131,6 @@ static void __exit i830_exit(void)
|
|||
module_init(i830_init);
|
||||
module_exit(i830_exit);
|
||||
|
||||
MODULE_AUTHOR( DRIVER_AUTHOR );
|
||||
MODULE_DESCRIPTION( DRIVER_DESC );
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
|
@ -63,14 +63,14 @@
|
|||
#define USE_IRQS 0
|
||||
|
||||
typedef struct drm_i830_buf_priv {
|
||||
u32 *in_use;
|
||||
int my_use_idx;
|
||||
u32 *in_use;
|
||||
int my_use_idx;
|
||||
int currently_mapped;
|
||||
void __user *virtual;
|
||||
void *kernel_virtual;
|
||||
} drm_i830_buf_priv_t;
|
||||
|
||||
typedef struct _drm_i830_ring_buffer{
|
||||
typedef struct _drm_i830_ring_buffer {
|
||||
int tail_mask;
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
|
@ -86,17 +86,17 @@ typedef struct drm_i830_private {
|
|||
drm_map_t *mmio_map;
|
||||
|
||||
drm_i830_sarea_t *sarea_priv;
|
||||
drm_i830_ring_buffer_t ring;
|
||||
drm_i830_ring_buffer_t ring;
|
||||
|
||||
void * hw_status_page;
|
||||
unsigned long counter;
|
||||
void *hw_status_page;
|
||||
unsigned long counter;
|
||||
|
||||
dma_addr_t dma_status_page;
|
||||
|
||||
drm_buf_t *mmap_buffer;
|
||||
|
||||
|
||||
u32 front_di1, back_di1, zi1;
|
||||
|
||||
|
||||
int back_offset;
|
||||
int depth_offset;
|
||||
int front_offset;
|
||||
|
@ -113,43 +113,39 @@ typedef struct drm_i830_private {
|
|||
int page_flipping;
|
||||
|
||||
wait_queue_head_t irq_queue;
|
||||
atomic_t irq_received;
|
||||
atomic_t irq_emitted;
|
||||
atomic_t irq_received;
|
||||
atomic_t irq_emitted;
|
||||
|
||||
int use_mi_batchbuffer_start;
|
||||
|
||||
} drm_i830_private_t;
|
||||
|
||||
extern drm_ioctl_desc_t i830_ioctls[];
|
||||
extern int i830_max_ioctl;
|
||||
|
||||
/* i830_dma.c */
|
||||
extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp);
|
||||
extern void i830_reclaim_buffers(drm_device_t * dev, struct file *filp);
|
||||
|
||||
/* i830_irq.c */
|
||||
extern int i830_irq_emit( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg );
|
||||
extern int i830_irq_wait( struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg );
|
||||
extern int i830_irq_emit(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i830_irq_wait(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
|
||||
extern void i830_driver_irq_preinstall( drm_device_t *dev );
|
||||
extern void i830_driver_irq_postinstall( drm_device_t *dev );
|
||||
extern void i830_driver_irq_uninstall( drm_device_t *dev );
|
||||
extern void i830_driver_pretakedown(drm_device_t *dev);
|
||||
extern void i830_driver_release(drm_device_t *dev, struct file *filp);
|
||||
extern int i830_driver_dma_quiescent(drm_device_t *dev);
|
||||
extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
|
||||
extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void i830_driver_irq_preinstall(drm_device_t * dev);
|
||||
extern void i830_driver_irq_postinstall(drm_device_t * dev);
|
||||
extern void i830_driver_irq_uninstall(drm_device_t * dev);
|
||||
extern void i830_driver_pretakedown(drm_device_t * dev);
|
||||
extern void i830_driver_release(drm_device_t * dev, struct file *filp);
|
||||
extern int i830_driver_dma_quiescent(drm_device_t * dev);
|
||||
extern void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp);
|
||||
extern int i830_driver_device_is_agp(drm_device_t * dev);
|
||||
|
||||
#define I830_BASE(reg) ((unsigned long) \
|
||||
dev_priv->mmio_map->handle)
|
||||
#define I830_ADDR(reg) (I830_BASE(reg) + reg)
|
||||
#define I830_DEREF(reg) *(__volatile__ unsigned int *)I830_ADDR(reg)
|
||||
#define I830_READ(reg) readl((volatile u32 *)I830_ADDR(reg))
|
||||
#define I830_WRITE(reg,val) writel(val, (volatile u32 *)I830_ADDR(reg))
|
||||
#define I830_DEREF16(reg) *(__volatile__ u16 *)I830_ADDR(reg)
|
||||
#define I830_READ16(reg) I830_DEREF16(reg)
|
||||
#define I830_WRITE16(reg,val) do { I830_DEREF16(reg) = val; } while (0)
|
||||
|
||||
|
||||
#define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
|
||||
#define I830_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
|
||||
#define I830_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
|
||||
#define I830_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)
|
||||
|
||||
#define I830_VERBOSE 0
|
||||
|
||||
|
@ -168,7 +164,6 @@ extern int i830_driver_device_is_agp(drm_device_t * dev);
|
|||
virt = dev_priv->ring.virtual_start; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
|
||||
*(volatile unsigned int *)(virt + outring) = n; \
|
||||
|
@ -184,8 +179,7 @@ extern int i830_driver_device_is_agp(drm_device_t * dev);
|
|||
I830_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
} while(0)
|
||||
|
||||
extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
|
||||
|
||||
extern int i830_wait_ring(drm_device_t * dev, int n, const char *caller);
|
||||
|
||||
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
|
||||
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
|
||||
|
@ -200,7 +194,6 @@ extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
|
|||
#define INST_OP_FLUSH 0x02000000
|
||||
#define INST_FLUSH_MAP_CACHE 0x00000001
|
||||
|
||||
|
||||
#define BB1_START_ADDR_MASK (~0x7)
|
||||
#define BB1_PROTECTED (1<<0)
|
||||
#define BB1_UNPROTECTED (0<<0)
|
||||
|
@ -213,7 +206,6 @@ extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
|
|||
|
||||
#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
|
||||
|
||||
|
||||
#define LP_RING 0x2030
|
||||
#define HP_RING 0x2040
|
||||
#define RING_TAIL 0x00
|
||||
|
@ -225,7 +217,7 @@ extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
|
|||
#define RING_START 0x08
|
||||
#define START_ADDR 0x0xFFFFF000
|
||||
#define RING_LEN 0x0C
|
||||
#define RING_NR_PAGES 0x001FF000
|
||||
#define RING_NR_PAGES 0x001FF000
|
||||
#define RING_REPORT_MASK 0x00000006
|
||||
#define RING_REPORT_64K 0x00000002
|
||||
#define RING_REPORT_128K 0x00000004
|
||||
|
@ -291,10 +283,9 @@ extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
|
|||
#define MI_BATCH_NON_SECURE (1)
|
||||
|
||||
#define MI_WAIT_FOR_EVENT ((0x3<<23))
|
||||
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
|
||||
#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
|
||||
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
|
||||
#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
|
||||
|
||||
#define MI_LOAD_SCAN_LINES_INCL ((0x12<<23))
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
|
@ -33,28 +33,27 @@
|
|||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/delay.h>
|
||||
|
||||
|
||||
irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS )
|
||||
irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)arg;
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
|
||||
u16 temp;
|
||||
drm_device_t *dev = (drm_device_t *) arg;
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
u16 temp;
|
||||
|
||||
temp = I830_READ16(I830REG_INT_IDENTITY_R);
|
||||
temp = I830_READ16(I830REG_INT_IDENTITY_R);
|
||||
DRM_DEBUG("%x\n", temp);
|
||||
|
||||
if ( !( temp & 2 ) )
|
||||
if (!(temp & 2))
|
||||
return IRQ_NONE;
|
||||
|
||||
I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
|
||||
I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
|
||||
|
||||
atomic_inc(&dev_priv->irq_received);
|
||||
wake_up_interruptible(&dev_priv->irq_queue);
|
||||
wake_up_interruptible(&dev_priv->irq_queue);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int i830_emit_irq(drm_device_t *dev)
|
||||
static int i830_emit_irq(drm_device_t * dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
|
@ -63,27 +62,25 @@ static int i830_emit_irq(drm_device_t *dev)
|
|||
|
||||
atomic_inc(&dev_priv->irq_emitted);
|
||||
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING( 0 );
|
||||
OUT_RING( GFX_OP_USER_INTERRUPT );
|
||||
ADVANCE_LP_RING();
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(0);
|
||||
OUT_RING(GFX_OP_USER_INTERRUPT);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
return atomic_read(&dev_priv->irq_emitted);
|
||||
}
|
||||
|
||||
|
||||
static int i830_wait_irq(drm_device_t *dev, int irq_nr)
|
||||
static int i830_wait_irq(drm_device_t * dev, int irq_nr)
|
||||
{
|
||||
drm_i830_private_t *dev_priv =
|
||||
(drm_i830_private_t *)dev->dev_private;
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
unsigned long end = jiffies + HZ*3;
|
||||
unsigned long end = jiffies + HZ * 3;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
if (atomic_read(&dev_priv->irq_received) >= irq_nr)
|
||||
return 0;
|
||||
if (atomic_read(&dev_priv->irq_received) >= irq_nr)
|
||||
return 0;
|
||||
|
||||
dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
|
||||
|
||||
|
@ -91,21 +88,21 @@ static int i830_wait_irq(drm_device_t *dev, int irq_nr)
|
|||
|
||||
for (;;) {
|
||||
__set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (atomic_read(&dev_priv->irq_received) >= irq_nr)
|
||||
break;
|
||||
if((signed)(end - jiffies) <= 0) {
|
||||
if (atomic_read(&dev_priv->irq_received) >= irq_nr)
|
||||
break;
|
||||
if ((signed)(end - jiffies) <= 0) {
|
||||
DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
|
||||
I830_READ16( I830REG_INT_IDENTITY_R ),
|
||||
I830_READ16( I830REG_INT_MASK_R ),
|
||||
I830_READ16( I830REG_INT_ENABLE_R ),
|
||||
I830_READ16( I830REG_HWSTAM ));
|
||||
I830_READ16(I830REG_INT_IDENTITY_R),
|
||||
I830_READ16(I830REG_INT_MASK_R),
|
||||
I830_READ16(I830REG_INT_ENABLE_R),
|
||||
I830_READ16(I830REG_HWSTAM));
|
||||
|
||||
ret = -EBUSY; /* Lockup? Missed irq? */
|
||||
ret = -EBUSY; /* Lockup? Missed irq? */
|
||||
break;
|
||||
}
|
||||
schedule_timeout(HZ*3);
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR;
|
||||
schedule_timeout(HZ * 3);
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -115,89 +112,87 @@ static int i830_wait_irq(drm_device_t *dev, int irq_nr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Needs the lock as it touches the ring.
|
||||
*/
|
||||
int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg )
|
||||
int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
drm_i830_irq_emit_t emit;
|
||||
int result;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if ( !dev_priv ) {
|
||||
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user( &emit, (drm_i830_irq_emit_t __user *)arg, sizeof(emit) ))
|
||||
if (copy_from_user
|
||||
(&emit, (drm_i830_irq_emit_t __user *) arg, sizeof(emit)))
|
||||
return -EFAULT;
|
||||
|
||||
result = i830_emit_irq( dev );
|
||||
result = i830_emit_irq(dev);
|
||||
|
||||
if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) {
|
||||
DRM_ERROR( "copy_to_user\n" );
|
||||
if (copy_to_user(emit.irq_seq, &result, sizeof(int))) {
|
||||
DRM_ERROR("copy_to_user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Doesn't need the hardware lock.
|
||||
*/
|
||||
int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg )
|
||||
int i830_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
drm_i830_irq_wait_t irqwait;
|
||||
|
||||
if ( !dev_priv ) {
|
||||
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user( &irqwait, (drm_i830_irq_wait_t __user *)arg,
|
||||
sizeof(irqwait) ))
|
||||
if (copy_from_user(&irqwait, (drm_i830_irq_wait_t __user *) arg,
|
||||
sizeof(irqwait)))
|
||||
return -EFAULT;
|
||||
|
||||
return i830_wait_irq( dev, irqwait.irq_seq );
|
||||
return i830_wait_irq(dev, irqwait.irq_seq);
|
||||
}
|
||||
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void i830_driver_irq_preinstall( drm_device_t *dev ) {
|
||||
drm_i830_private_t *dev_priv =
|
||||
(drm_i830_private_t *)dev->dev_private;
|
||||
void i830_driver_irq_preinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
|
||||
I830_WRITE16( I830REG_HWSTAM, 0xffff );
|
||||
I830_WRITE16( I830REG_INT_MASK_R, 0x0 );
|
||||
I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
|
||||
I830_WRITE16(I830REG_HWSTAM, 0xffff);
|
||||
I830_WRITE16(I830REG_INT_MASK_R, 0x0);
|
||||
I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
|
||||
atomic_set(&dev_priv->irq_received, 0);
|
||||
atomic_set(&dev_priv->irq_emitted, 0);
|
||||
init_waitqueue_head(&dev_priv->irq_queue);
|
||||
}
|
||||
|
||||
void i830_driver_irq_postinstall( drm_device_t *dev ) {
|
||||
drm_i830_private_t *dev_priv =
|
||||
(drm_i830_private_t *)dev->dev_private;
|
||||
void i830_driver_irq_postinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
|
||||
I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
|
||||
I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
|
||||
}
|
||||
|
||||
void i830_driver_irq_uninstall( drm_device_t *dev ) {
|
||||
drm_i830_private_t *dev_priv =
|
||||
(drm_i830_private_t *)dev->dev_private;
|
||||
void i830_driver_irq_uninstall(drm_device_t * dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
|
||||
I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
|
||||
I830_WRITE16(I830REG_INT_MASK_R, 0xffff);
|
||||
I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
|
||||
}
|
||||
|
|
|
@ -85,14 +85,14 @@ static int i915_dma_cleanup(drm_device_t * dev)
|
|||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq)
|
||||
drm_irq_uninstall (dev);
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv =
|
||||
(drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
if (dev_priv->ring.virtual_start) {
|
||||
drm_core_ioremapfree( &dev_priv->ring.map, dev);
|
||||
drm_core_ioremapfree(&dev_priv->ring.map, dev);
|
||||
}
|
||||
|
||||
if (dev_priv->status_page_dmah) {
|
||||
|
@ -101,8 +101,8 @@ static int i915_dma_cleanup(drm_device_t * dev)
|
|||
I915_WRITE(0x02080, 0x1ffff000);
|
||||
}
|
||||
|
||||
drm_free (dev->dev_private, sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(dev->dev_private, sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
|
||||
dev->dev_private = NULL;
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ static int i915_initialize(drm_device_t * dev,
|
|||
dev_priv->ring.map.flags = 0;
|
||||
dev_priv->ring.map.mtrr = 0;
|
||||
|
||||
drm_core_ioremap( &dev_priv->ring.map, dev );
|
||||
drm_core_ioremap(&dev_priv->ring.map, dev);
|
||||
|
||||
if (dev_priv->ring.map.handle == NULL) {
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
|
@ -243,8 +243,8 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
|
|||
|
||||
switch (init.func) {
|
||||
case I915_INIT_DMA:
|
||||
dev_priv = drm_alloc (sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
dev_priv = drm_alloc(sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
if (dev_priv == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
retcode = i915_initialize(dev, dev_priv, &init);
|
||||
|
@ -297,7 +297,7 @@ static int do_validate_cmd(int cmd)
|
|||
case 0x1c:
|
||||
return 1;
|
||||
case 0x1d:
|
||||
switch ((cmd>>16)&0xff) {
|
||||
switch ((cmd >> 16) & 0xff) {
|
||||
case 0x3:
|
||||
return (cmd & 0x1f) + 2;
|
||||
case 0x4:
|
||||
|
@ -699,20 +699,20 @@ static int i915_setparam(DRM_IOCTL_ARGS)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void i915_driver_pretakedown(drm_device_t *dev)
|
||||
void i915_driver_pretakedown(drm_device_t * dev)
|
||||
{
|
||||
if ( dev->dev_private ) {
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
i915_mem_takedown( &(dev_priv->agp_heap) );
|
||||
}
|
||||
i915_dma_cleanup( dev );
|
||||
i915_mem_takedown(&(dev_priv->agp_heap));
|
||||
}
|
||||
i915_dma_cleanup(dev);
|
||||
}
|
||||
|
||||
void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp)
|
||||
void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)
|
||||
{
|
||||
if ( dev->dev_private ) {
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
i915_mem_release( dev, filp, dev_priv->agp_heap );
|
||||
i915_mem_release(dev, filp, dev_priv->agp_heap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,36 +34,34 @@
|
|||
|
||||
#include "drm_pciids.h"
|
||||
|
||||
static int postinit( struct drm_device *dev, unsigned long flags )
|
||||
static int postinit(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
dev->counters += 4;
|
||||
dev->types[6] = _DRM_STAT_IRQ;
|
||||
dev->types[7] = _DRM_STAT_PRIMARY;
|
||||
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||
dev->types[9] = _DRM_STAT_DMA;
|
||||
|
||||
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE,
|
||||
dev->primary.minor,
|
||||
pci_pretty_name(dev->pdev)
|
||||
);
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int version( drm_version_t *version )
|
||||
static int version(drm_version_t * version)
|
||||
{
|
||||
int len;
|
||||
|
||||
version->version_major = DRIVER_MAJOR;
|
||||
version->version_minor = DRIVER_MINOR;
|
||||
version->version_patchlevel = DRIVER_PATCHLEVEL;
|
||||
DRM_COPY( version->name, DRIVER_NAME );
|
||||
DRM_COPY( version->date, DRIVER_DATE );
|
||||
DRM_COPY( version->desc, DRIVER_DESC );
|
||||
DRM_COPY(version->name, DRIVER_NAME);
|
||||
DRM_COPY(version->date, DRIVER_DATE);
|
||||
DRM_COPY(version->desc, DRIVER_DESC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -71,12 +69,10 @@ static struct pci_device_id pciidlist[] = {
|
|||
i915_PCI_IDS
|
||||
};
|
||||
|
||||
extern drm_ioctl_desc_t i915_ioctls[];
|
||||
extern int i915_max_ioctl;
|
||||
|
||||
static struct drm_driver driver = {
|
||||
.driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
.pretakedown = i915_driver_pretakedown,
|
||||
.prerelease = i915_driver_prerelease,
|
||||
.device_is_agp = i915_driver_device_is_agp,
|
||||
|
@ -91,21 +87,21 @@ static struct drm_driver driver = {
|
|||
.version = version,
|
||||
.ioctls = i915_ioctls,
|
||||
.fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = i915_compat_ioctl,
|
||||
.compat_ioctl = i915_compat_ioctl,
|
||||
#endif
|
||||
},
|
||||
},
|
||||
.pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
}
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init i915_init(void)
|
||||
|
@ -122,6 +118,6 @@ static void __exit i915_exit(void)
|
|||
module_init(i915_init);
|
||||
module_exit(i915_exit);
|
||||
|
||||
MODULE_AUTHOR( DRIVER_AUTHOR );
|
||||
MODULE_DESCRIPTION( DRIVER_DESC );
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
|
|
@ -99,20 +99,23 @@ typedef struct drm_i915_private {
|
|||
struct mem_block *agp_heap;
|
||||
} drm_i915_private_t;
|
||||
|
||||
extern drm_ioctl_desc_t i915_ioctls[];
|
||||
extern int i915_max_ioctl;
|
||||
|
||||
/* i915_dma.c */
|
||||
extern void i915_kernel_lost_context(drm_device_t * dev);
|
||||
extern void i915_driver_pretakedown(drm_device_t *dev);
|
||||
extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
|
||||
extern int i915_driver_device_is_agp(drm_device_t *dev);
|
||||
extern void i915_driver_pretakedown(drm_device_t * dev);
|
||||
extern void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp);
|
||||
extern int i915_driver_device_is_agp(drm_device_t * dev);
|
||||
|
||||
/* i915_irq.c */
|
||||
extern int i915_irq_emit(DRM_IOCTL_ARGS);
|
||||
extern int i915_irq_wait(DRM_IOCTL_ARGS);
|
||||
|
||||
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void i915_driver_irq_preinstall(drm_device_t *dev);
|
||||
extern void i915_driver_irq_postinstall(drm_device_t *dev);
|
||||
extern void i915_driver_irq_uninstall(drm_device_t *dev);
|
||||
extern void i915_driver_irq_preinstall(drm_device_t * dev);
|
||||
extern void i915_driver_irq_postinstall(drm_device_t * dev);
|
||||
extern void i915_driver_irq_uninstall(drm_device_t * dev);
|
||||
|
||||
/* i915_mem.c */
|
||||
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
|
||||
|
@ -125,7 +128,6 @@ extern void i915_mem_release(drm_device_t * dev,
|
|||
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
|
||||
#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
|
||||
#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
|
||||
#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* 32-bit ioctl compatibility routines for the i915 DRM.
|
||||
*
|
||||
* \author Alan Hourihane <alanh@fairlite.demon.co.uk>
|
||||
* \author Alan Hourihane <alanh@fairlite.demon.co.uk>
|
||||
*
|
||||
*
|
||||
* Copyright (C) Paul Mackerras 2005
|
||||
|
@ -42,51 +42,55 @@ typedef struct _drm_i915_batchbuffer32 {
|
|||
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
|
||||
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
|
||||
int num_cliprects; /* mulitpass with multiple cliprects? */
|
||||
u32 cliprects; /* pointer to userspace cliprects */
|
||||
u32 cliprects; /* pointer to userspace cliprects */
|
||||
} drm_i915_batchbuffer32_t;
|
||||
|
||||
static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_i915_batchbuffer32_t batchbuffer32;
|
||||
drm_i915_batchbuffer_t __user *batchbuffer;
|
||||
|
||||
if (copy_from_user(&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
|
||||
|
||||
if (copy_from_user
|
||||
(&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
|
||||
return -EFAULT;
|
||||
|
||||
|
||||
batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer));
|
||||
if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer))
|
||||
|| __put_user(batchbuffer32.start, &batchbuffer->start)
|
||||
|| __put_user(batchbuffer32.used, &batchbuffer->used)
|
||||
|| __put_user(batchbuffer32.DR1, &batchbuffer->DR1)
|
||||
|| __put_user(batchbuffer32.DR4, &batchbuffer->DR4)
|
||||
|| __put_user(batchbuffer32.num_cliprects, &batchbuffer->num_cliprects)
|
||||
|| __put_user(batchbuffer32.num_cliprects,
|
||||
&batchbuffer->num_cliprects)
|
||||
|| __put_user((int __user *)(unsigned long)batchbuffer32.cliprects,
|
||||
&batchbuffer->cliprects))
|
||||
return -EFAULT;
|
||||
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_I915_BATCHBUFFER, (unsigned long) batchbuffer);
|
||||
DRM_IOCTL_I915_BATCHBUFFER,
|
||||
(unsigned long)batchbuffer);
|
||||
}
|
||||
|
||||
typedef struct _drm_i915_cmdbuffer32 {
|
||||
u32 buf; /* pointer to userspace command buffer */
|
||||
u32 buf; /* pointer to userspace command buffer */
|
||||
int sz; /* nr bytes in buf */
|
||||
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
|
||||
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
|
||||
int num_cliprects; /* mulitpass with multiple cliprects? */
|
||||
u32 cliprects; /* pointer to userspace cliprects */
|
||||
u32 cliprects; /* pointer to userspace cliprects */
|
||||
} drm_i915_cmdbuffer32_t;
|
||||
|
||||
static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_i915_cmdbuffer32_t cmdbuffer32;
|
||||
drm_i915_cmdbuffer_t __user *cmdbuffer;
|
||||
|
||||
if (copy_from_user(&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
|
||||
|
||||
if (copy_from_user
|
||||
(&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
|
||||
return -EFAULT;
|
||||
|
||||
|
||||
cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer));
|
||||
if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer))
|
||||
|| __put_user((int __user *)(unsigned long)cmdbuffer32.buf,
|
||||
|
@ -98,9 +102,9 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
|
|||
|| __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects,
|
||||
&cmdbuffer->cliprects))
|
||||
return -EFAULT;
|
||||
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_I915_CMDBUFFER, (unsigned long) cmdbuffer);
|
||||
DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
|
||||
}
|
||||
|
||||
typedef struct drm_i915_irq_emit32 {
|
||||
|
@ -108,12 +112,12 @@ typedef struct drm_i915_irq_emit32 {
|
|||
} drm_i915_irq_emit32_t;
|
||||
|
||||
static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_i915_irq_emit32_t req32;
|
||||
drm_i915_irq_emit_t __user *request;
|
||||
|
||||
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
|
||||
if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
|
||||
return -EFAULT;
|
||||
|
||||
request = compat_alloc_user_space(sizeof(*request));
|
||||
|
@ -123,7 +127,7 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_I915_IRQ_EMIT, (unsigned long) request);
|
||||
DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
|
||||
}
|
||||
typedef struct drm_i915_getparam32 {
|
||||
int param;
|
||||
|
@ -131,12 +135,12 @@ typedef struct drm_i915_getparam32 {
|
|||
} drm_i915_getparam32_t;
|
||||
|
||||
static int compat_i915_getparam(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_i915_getparam32_t req32;
|
||||
drm_i915_getparam_t __user *request;
|
||||
|
||||
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
|
||||
if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
|
||||
return -EFAULT;
|
||||
|
||||
request = compat_alloc_user_space(sizeof(*request));
|
||||
|
@ -147,7 +151,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_I915_GETPARAM, (unsigned long) request);
|
||||
DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
|
||||
}
|
||||
|
||||
typedef struct drm_i915_mem_alloc32 {
|
||||
|
@ -158,12 +162,12 @@ typedef struct drm_i915_mem_alloc32 {
|
|||
} drm_i915_mem_alloc32_t;
|
||||
|
||||
static int compat_i915_alloc(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_i915_mem_alloc32_t req32;
|
||||
drm_i915_mem_alloc_t __user *request;
|
||||
|
||||
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
|
||||
if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
|
||||
return -EFAULT;
|
||||
|
||||
request = compat_alloc_user_space(sizeof(*request));
|
||||
|
@ -176,10 +180,9 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
return drm_ioctl(file->f_dentry->d_inode, file,
|
||||
DRM_IOCTL_I915_ALLOC, (unsigned long) request);
|
||||
DRM_IOCTL_I915_ALLOC, (unsigned long)request);
|
||||
}
|
||||
|
||||
|
||||
drm_ioctl_compat_t *i915_compat_ioctls[] = {
|
||||
[DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
|
||||
[DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
|
||||
|
@ -197,8 +200,7 @@ drm_ioctl_compat_t *i915_compat_ioctls[] = {
|
|||
* \param arg user argument.
|
||||
* \return zero on success or negative number on failure.
|
||||
*/
|
||||
long i915_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned int nr = DRM_IOCTL_NR(cmd);
|
||||
drm_ioctl_compat_t *fn = NULL;
|
||||
|
@ -206,13 +208,13 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd,
|
|||
|
||||
if (nr < DRM_COMMAND_BASE)
|
||||
return drm_compat_ioctl(filp, cmd, arg);
|
||||
|
||||
|
||||
if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
|
||||
fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
|
||||
|
||||
lock_kernel(); /* XXX for now */
|
||||
if (fn != NULL)
|
||||
ret = (*fn)(filp, cmd, arg);
|
||||
ret = (*fn) (filp, cmd, arg);
|
||||
else
|
||||
ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
|
||||
unlock_kernel();
|
||||
|
|
|
@ -86,7 +86,7 @@ static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
|
|||
}
|
||||
|
||||
/* Very simple allocator for agp memory, working on a static range
|
||||
* already mapped into each client's address space.
|
||||
* already mapped into each client's address space.
|
||||
*/
|
||||
|
||||
static struct mem_block *split_block(struct mem_block *p, int start, int size,
|
||||
|
@ -94,7 +94,8 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
|
|||
{
|
||||
/* Maybe cut off the start of an existing block */
|
||||
if (start > p->start) {
|
||||
struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
|
||||
struct mem_block *newblock =
|
||||
drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
|
||||
if (!newblock)
|
||||
goto out;
|
||||
newblock->start = start;
|
||||
|
@ -110,7 +111,8 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
|
|||
|
||||
/* Maybe cut off the end of an existing block */
|
||||
if (size < p->size) {
|
||||
struct mem_block *newblock = drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
|
||||
struct mem_block *newblock =
|
||||
drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
|
||||
if (!newblock)
|
||||
goto out;
|
||||
newblock->start = start + size;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,10 +44,10 @@
|
|||
|
||||
/* WARP pipe flags
|
||||
*/
|
||||
#define MGA_F 0x1 /* fog */
|
||||
#define MGA_A 0x2 /* alpha */
|
||||
#define MGA_S 0x4 /* specular */
|
||||
#define MGA_T2 0x8 /* multitexture */
|
||||
#define MGA_F 0x1 /* fog */
|
||||
#define MGA_A 0x2 /* alpha */
|
||||
#define MGA_S 0x4 /* specular */
|
||||
#define MGA_T2 0x8 /* multitexture */
|
||||
|
||||
#define MGA_WARP_TGZ 0
|
||||
#define MGA_WARP_TGZF (MGA_F)
|
||||
|
@ -66,14 +66,14 @@
|
|||
#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A)
|
||||
#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A)
|
||||
|
||||
#define MGA_MAX_G200_PIPES 8 /* no multitex */
|
||||
#define MGA_MAX_G200_PIPES 8 /* no multitex */
|
||||
#define MGA_MAX_G400_PIPES 16
|
||||
#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
|
||||
#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */
|
||||
#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */
|
||||
|
||||
#define MGA_CARD_TYPE_G200 1
|
||||
#define MGA_CARD_TYPE_G400 2
|
||||
#define MGA_CARD_TYPE_G450 3 /* not currently used */
|
||||
#define MGA_CARD_TYPE_G450 3 /* not currently used */
|
||||
#define MGA_CARD_TYPE_G550 4
|
||||
|
||||
#define MGA_FRONT 0x1
|
||||
|
@ -86,14 +86,14 @@
|
|||
#define MGA_UPLOAD_TEX0 0x2
|
||||
#define MGA_UPLOAD_TEX1 0x4
|
||||
#define MGA_UPLOAD_PIPE 0x8
|
||||
#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
|
||||
#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
|
||||
#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
|
||||
#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
|
||||
#define MGA_UPLOAD_2D 0x40
|
||||
#define MGA_WAIT_AGE 0x80 /* handled client-side */
|
||||
#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
|
||||
#define MGA_WAIT_AGE 0x80 /* handled client-side */
|
||||
#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
|
||||
#if 0
|
||||
#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
|
||||
quiescent */
|
||||
#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
|
||||
quiescent */
|
||||
#endif
|
||||
|
||||
/* 32 buffers of 64k each, total 2 meg.
|
||||
|
@ -120,8 +120,7 @@
|
|||
|
||||
#define DRM_MGA_IDLE_RETRY 2048
|
||||
|
||||
#endif /* __MGA_SAREA_DEFINES__ */
|
||||
|
||||
#endif /* __MGA_SAREA_DEFINES__ */
|
||||
|
||||
/* Setup registers for 3D context
|
||||
*/
|
||||
|
@ -165,25 +164,25 @@ typedef struct {
|
|||
/* General aging mechanism
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int head; /* Position of head pointer */
|
||||
unsigned int wrap; /* Primary DMA wrap count */
|
||||
unsigned int head; /* Position of head pointer */
|
||||
unsigned int wrap; /* Primary DMA wrap count */
|
||||
} drm_mga_age_t;
|
||||
|
||||
typedef struct _drm_mga_sarea {
|
||||
/* The channel for communication of state information to the kernel
|
||||
* on firing a vertex dma buffer.
|
||||
*/
|
||||
drm_mga_context_regs_t context_state;
|
||||
drm_mga_server_regs_t server_state;
|
||||
drm_mga_texture_regs_t tex_state[2];
|
||||
unsigned int warp_pipe;
|
||||
unsigned int dirty;
|
||||
unsigned int vertsize;
|
||||
drm_mga_context_regs_t context_state;
|
||||
drm_mga_server_regs_t server_state;
|
||||
drm_mga_texture_regs_t tex_state[2];
|
||||
unsigned int warp_pipe;
|
||||
unsigned int dirty;
|
||||
unsigned int vertsize;
|
||||
|
||||
/* The current cliprects, or a subset thereof.
|
||||
*/
|
||||
drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
|
||||
unsigned int nbox;
|
||||
drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
|
||||
unsigned int nbox;
|
||||
|
||||
/* Information about the most recently used 3d drawable. The
|
||||
* client fills in the req_* fields, the server fills in the
|
||||
|
@ -192,18 +191,18 @@ typedef struct _drm_mga_sarea {
|
|||
* The client clears the exported_drawable field before
|
||||
* clobbering the boxes data.
|
||||
*/
|
||||
unsigned int req_drawable; /* the X drawable id */
|
||||
unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
|
||||
unsigned int req_drawable; /* the X drawable id */
|
||||
unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
|
||||
|
||||
unsigned int exported_drawable;
|
||||
unsigned int exported_drawable;
|
||||
unsigned int exported_index;
|
||||
unsigned int exported_stamp;
|
||||
unsigned int exported_buffers;
|
||||
unsigned int exported_nfront;
|
||||
unsigned int exported_nback;
|
||||
unsigned int exported_stamp;
|
||||
unsigned int exported_buffers;
|
||||
unsigned int exported_nfront;
|
||||
unsigned int exported_nback;
|
||||
int exported_back_x, exported_front_x, exported_w;
|
||||
int exported_back_y, exported_front_y, exported_h;
|
||||
drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
|
||||
drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
|
||||
|
||||
/* Counters for aging textures and for client-side throttling.
|
||||
*/
|
||||
|
@ -211,21 +210,20 @@ typedef struct _drm_mga_sarea {
|
|||
unsigned int last_wrap;
|
||||
|
||||
drm_mga_age_t last_frame;
|
||||
unsigned int last_enqueue; /* last time a buffer was enqueued */
|
||||
unsigned int last_enqueue; /* last time a buffer was enqueued */
|
||||
unsigned int last_dispatch; /* age of the most recently dispatched buffer */
|
||||
unsigned int last_quiescent; /* */
|
||||
unsigned int last_quiescent; /* */
|
||||
|
||||
/* LRU lists for texture memory in agp space and on the card.
|
||||
*/
|
||||
drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1];
|
||||
drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
|
||||
unsigned int texAge[MGA_NR_TEX_HEAPS];
|
||||
|
||||
/* Mechanism to validate card state.
|
||||
*/
|
||||
int ctxOwner;
|
||||
int ctxOwner;
|
||||
} drm_mga_sarea_t;
|
||||
|
||||
|
||||
/* MGA specific ioctls
|
||||
* The device specific ioctl range is 0x40 to 0x79.
|
||||
*/
|
||||
|
@ -247,7 +245,6 @@ typedef struct _drm_mga_sarea {
|
|||
#define DRM_MGA_WAIT_FENCE 0x0b
|
||||
#define DRM_MGA_DMA_BOOTSTRAP 0x0c
|
||||
|
||||
|
||||
#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
|
||||
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
|
||||
#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET)
|
||||
|
@ -263,33 +260,33 @@ typedef struct _drm_mga_sarea {
|
|||
#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t)
|
||||
|
||||
typedef struct _drm_mga_warp_index {
|
||||
int installed;
|
||||
unsigned long phys_addr;
|
||||
int size;
|
||||
int installed;
|
||||
unsigned long phys_addr;
|
||||
int size;
|
||||
} drm_mga_warp_index_t;
|
||||
|
||||
typedef struct drm_mga_init {
|
||||
enum {
|
||||
MGA_INIT_DMA = 0x01,
|
||||
MGA_CLEANUP_DMA = 0x02
|
||||
enum {
|
||||
MGA_INIT_DMA = 0x01,
|
||||
MGA_CLEANUP_DMA = 0x02
|
||||
} func;
|
||||
|
||||
unsigned long sarea_priv_offset;
|
||||
unsigned long sarea_priv_offset;
|
||||
|
||||
int chipset;
|
||||
int sgram;
|
||||
int sgram;
|
||||
|
||||
unsigned int maccess;
|
||||
|
||||
unsigned int fb_cpp;
|
||||
unsigned int fb_cpp;
|
||||
unsigned int front_offset, front_pitch;
|
||||
unsigned int back_offset, back_pitch;
|
||||
unsigned int back_offset, back_pitch;
|
||||
|
||||
unsigned int depth_cpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
unsigned int depth_cpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
|
||||
unsigned int texture_offset[MGA_NR_TEX_HEAPS];
|
||||
unsigned int texture_size[MGA_NR_TEX_HEAPS];
|
||||
unsigned int texture_offset[MGA_NR_TEX_HEAPS];
|
||||
unsigned int texture_size[MGA_NR_TEX_HEAPS];
|
||||
|
||||
unsigned long fb_offset;
|
||||
unsigned long mmio_offset;
|
||||
|
@ -302,64 +299,59 @@ typedef struct drm_mga_init {
|
|||
typedef struct drm_mga_dma_bootstrap {
|
||||
/**
|
||||
* \name AGP texture region
|
||||
*
|
||||
*
|
||||
* On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will
|
||||
* be filled in with the actual AGP texture settings.
|
||||
*
|
||||
*
|
||||
* \warning
|
||||
* If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode
|
||||
* is zero, it means that PCI memory (most likely through the use of
|
||||
* an IOMMU) is being used for "AGP" textures.
|
||||
*/
|
||||
/*@{*/
|
||||
/*@{ */
|
||||
unsigned long texture_handle; /**< Handle used to map AGP textures. */
|
||||
uint32_t texture_size; /**< Size of the AGP texture region. */
|
||||
/*@}*/
|
||||
|
||||
uint32_t texture_size; /**< Size of the AGP texture region. */
|
||||
/*@} */
|
||||
|
||||
/**
|
||||
* Requested size of the primary DMA region.
|
||||
*
|
||||
*
|
||||
* On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
|
||||
* filled in with the actual AGP mode. If AGP was not available
|
||||
*/
|
||||
uint32_t primary_size;
|
||||
|
||||
|
||||
/**
|
||||
* Requested number of secondary DMA buffers.
|
||||
*
|
||||
*
|
||||
* On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
|
||||
* filled in with the actual number of secondary DMA buffers
|
||||
* allocated. Particularly when PCI DMA is used, this may be
|
||||
* (subtantially) less than the number requested.
|
||||
*/
|
||||
uint32_t secondary_bin_count;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Requested size of each secondary DMA buffer.
|
||||
*
|
||||
*
|
||||
* While the kernel \b is free to reduce
|
||||
* dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed
|
||||
* to reduce dma_mga_dma_bootstrap::secondary_bin_size.
|
||||
*/
|
||||
uint32_t secondary_bin_size;
|
||||
|
||||
|
||||
/**
|
||||
* Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X,
|
||||
* \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is
|
||||
* zero, it means that PCI DMA should be used, even if AGP is
|
||||
* possible.
|
||||
*
|
||||
*
|
||||
* On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
|
||||
* filled in with the actual AGP mode. If AGP was not available
|
||||
* (i.e., PCI DMA was used), this value will be zero.
|
||||
*/
|
||||
uint32_t agp_mode;
|
||||
|
||||
|
||||
/**
|
||||
* Desired AGP GART size, measured in megabytes.
|
||||
*/
|
||||
|
@ -375,16 +367,16 @@ typedef struct drm_mga_clear {
|
|||
} drm_mga_clear_t;
|
||||
|
||||
typedef struct drm_mga_vertex {
|
||||
int idx; /* buffer to queue */
|
||||
int used; /* bytes in use */
|
||||
int discard; /* client finished with buffer? */
|
||||
int idx; /* buffer to queue */
|
||||
int used; /* bytes in use */
|
||||
int discard; /* client finished with buffer? */
|
||||
} drm_mga_vertex_t;
|
||||
|
||||
typedef struct drm_mga_indices {
|
||||
int idx; /* buffer to queue */
|
||||
int idx; /* buffer to queue */
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
int discard; /* client finished with buffer? */
|
||||
int discard; /* client finished with buffer? */
|
||||
} drm_mga_indices_t;
|
||||
|
||||
typedef struct drm_mga_iload {
|
||||
|
@ -400,12 +392,12 @@ typedef struct _drm_mga_blit {
|
|||
int src_pitch, dst_pitch;
|
||||
int delta_sx, delta_sy;
|
||||
int delta_dx, delta_dy;
|
||||
int height, ydir; /* flip image vertically */
|
||||
int height, ydir; /* flip image vertically */
|
||||
int source_pitch, dest_pitch;
|
||||
} drm_mga_blit_t;
|
||||
|
||||
/* 3.1: An ioctl to get parameters that aren't available to the 3d
|
||||
* client any other way.
|
||||
* client any other way.
|
||||
*/
|
||||
#define MGA_PARAM_IRQ_NR 1
|
||||
|
||||
|
|
|
@ -35,14 +35,13 @@
|
|||
#include "mga_drm.h"
|
||||
#include "mga_drv.h"
|
||||
|
||||
|
||||
#include "drm_pciids.h"
|
||||
|
||||
static int mga_driver_device_is_agp(drm_device_t * dev);
|
||||
static int postinit( struct drm_device *dev, unsigned long flags )
|
||||
static int postinit(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
drm_mga_private_t * const dev_priv =
|
||||
(drm_mga_private_t *) dev->dev_private;
|
||||
drm_mga_private_t *const dev_priv =
|
||||
(drm_mga_private_t *) dev->dev_private;
|
||||
|
||||
dev_priv->mmio_base = pci_resource_start(dev->pdev, 1);
|
||||
dev_priv->mmio_size = pci_resource_len(dev->pdev, 1);
|
||||
|
@ -52,28 +51,26 @@ static int postinit( struct drm_device *dev, unsigned long flags )
|
|||
dev->types[7] = _DRM_STAT_PRIMARY;
|
||||
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||
|
||||
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE,
|
||||
dev->primary.minor,
|
||||
pci_pretty_name(dev->pdev)
|
||||
);
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
|
||||
DRIVER_NAME,
|
||||
DRIVER_MAJOR,
|
||||
DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL,
|
||||
DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int version( drm_version_t *version )
|
||||
static int version(drm_version_t * version)
|
||||
{
|
||||
int len;
|
||||
|
||||
version->version_major = DRIVER_MAJOR;
|
||||
version->version_minor = DRIVER_MINOR;
|
||||
version->version_patchlevel = DRIVER_PATCHLEVEL;
|
||||
DRM_COPY( version->name, DRIVER_NAME );
|
||||
DRM_COPY( version->date, DRIVER_DATE );
|
||||
DRM_COPY( version->desc, DRIVER_DESC );
|
||||
DRM_COPY(version->name, DRIVER_NAME);
|
||||
DRM_COPY(version->date, DRIVER_DATE);
|
||||
DRM_COPY(version->desc, DRIVER_DESC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -81,11 +78,11 @@ static struct pci_device_id pciidlist[] = {
|
|||
mga_PCI_IDS
|
||||
};
|
||||
|
||||
extern drm_ioctl_desc_t mga_ioctls[];
|
||||
extern int mga_max_ioctl;
|
||||
|
||||
static struct drm_driver driver = {
|
||||
.driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
|
||||
DRIVER_IRQ_VBL,
|
||||
.preinit = mga_driver_preinit,
|
||||
.postcleanup = mga_driver_postcleanup,
|
||||
.pretakedown = mga_driver_pretakedown,
|
||||
|
@ -104,21 +101,21 @@ static struct drm_driver driver = {
|
|||
.ioctls = mga_ioctls,
|
||||
.dma_ioctl = mga_dma_buffers,
|
||||
.fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.ioctl = drm_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = mga_compat_ioctl,
|
||||
.compat_ioctl = mga_compat_ioctl,
|
||||
#endif
|
||||
},
|
||||
},
|
||||
.pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
}
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init mga_init(void)
|
||||
|
@ -135,8 +132,8 @@ static void __exit mga_exit(void)
|
|||
module_init(mga_init);
|
||||
module_exit(mga_exit);
|
||||
|
||||
MODULE_AUTHOR( DRIVER_AUTHOR );
|
||||
MODULE_DESCRIPTION( DRIVER_DESC );
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
||||
/**
|
||||
|
@ -151,10 +148,9 @@ MODULE_LICENSE("GPL and additional rights");
|
|||
* \returns
|
||||
* If the device is a PCI G450, zero is returned. Otherwise 2 is returned.
|
||||
*/
|
||||
int mga_driver_device_is_agp(drm_device_t * dev)
|
||||
static int mga_driver_device_is_agp(drm_device_t * dev)
|
||||
{
|
||||
const struct pci_dev * const pdev = dev->pdev;
|
||||
|
||||
const struct pci_dev *const pdev = dev->pdev;
|
||||
|
||||
/* There are PCI versions of the G450. These cards have the
|
||||
* same PCI ID as the AGP G450, but have an additional PCI-to-PCI
|
||||
|
@ -164,10 +160,10 @@ int mga_driver_device_is_agp(drm_device_t * dev)
|
|||
* device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
|
||||
* device.
|
||||
*/
|
||||
|
||||
if ( (pdev->device == 0x0525)
|
||||
&& (pdev->bus->self->vendor == 0x3388)
|
||||
&& (pdev->bus->self->device == 0x0021) ) {
|
||||
|
||||
if ((pdev->device == 0x0525)
|
||||
&& (pdev->bus->self->vendor == 0x3388)
|
||||
&& (pdev->bus->self->device == 0x0021)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue