Auto-update from upstream

This commit is contained in:
Tony Luck 2005-11-03 09:09:08 -08:00
commit 55725495f2
269 changed files with 26618 additions and 21464 deletions

View File

@ -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
---------------

View File

@ -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
-----------

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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 */

View File

@ -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();

View File

@ -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

View File

@ -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

52
arch/arm/lib/clear_user.S Normal file
View File

@ -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

View File

@ -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

View File

@ -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

101
arch/arm/lib/copy_to_user.S Normal file
View File

@ -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

View File

@ -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"

206
arch/arm/lib/memmove.S Normal file
View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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- :=

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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 =

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,6 @@
#
# Makefile for the linux kernel.
#
obj-y := core.o clock.o
obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o

View File

@ -0,0 +1,4 @@
zreladdr-y := 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000

View File

@ -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);

View File

@ -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);

View File

@ -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,
};

View File

@ -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

View File

@ -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

View File

@ -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> */

View File

@ -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

View File

@ -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();
}
/*

View File

@ -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;
}

View File

@ -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
}

View File

@ -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

View File

@ -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
*/

View File

@ -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
}

View File

@ -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 = {

View File

@ -26,6 +26,10 @@ config MMU
bool
default y
config SWIOTLB
bool
default y
config RWSEM_XCHGADD_ALGORITHM
bool
default y

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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:

View File

@ -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;

View File

@ -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--;
}

View File

@ -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);

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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;
}
/*@}*/

View File

@ -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);

View File

@ -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 */
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}

View File

@ -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,

View File

@ -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 )

View File

@ -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);
/*@}*/

View File

@ -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}

View File

@ -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

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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, &regs[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");

View File

@ -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

View File

@ -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_ */

View File

@ -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");

View File

@ -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

View File

@ -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_ */

View File

@ -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");

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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");

View File

@ -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)

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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