Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
cd585d2f
Commit
cd585d2f
authored
Sep 24, 2002
by
Patrick Mochel
Browse files
Options
Browse Files
Download
Plain Diff
Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin
into osdl.org:/home/mochel/src/kernel/devel/linux-2.5
parents
f6bec0e6
a9ee74e7
Changes
27
Show whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
1034 additions
and
409 deletions
+1034
-409
arch/alpha/Makefile
arch/alpha/Makefile
+3
-3
arch/alpha/kernel/entry.S
arch/alpha/kernel/entry.S
+24
-0
arch/alpha/lib/Makefile
arch/alpha/lib/Makefile
+4
-9
arch/alpha/math-emu/Makefile
arch/alpha/math-emu/Makefile
+2
-4
drivers/block/elevator.c
drivers/block/elevator.c
+24
-22
drivers/char/drm/Makefile
drivers/char/drm/Makefile
+1
-1
drivers/char/drm/drmP.h
drivers/char/drm/drmP.h
+3
-3
drivers/char/drm/drm_bufs.h
drivers/char/drm/drm_bufs.h
+1
-0
drivers/char/drm/drm_drv.h
drivers/char/drm/drm_drv.h
+2
-2
drivers/char/drm/drm_lock.h
drivers/char/drm/drm_lock.h
+1
-1
drivers/char/drm/drm_os_linux.h
drivers/char/drm/drm_os_linux.h
+3
-0
drivers/char/drm/i830.h
drivers/char/drm/i830.h
+6
-46
drivers/char/drm/i830_dma.c
drivers/char/drm/i830_dma.c
+137
-272
drivers/char/drm/i830_drv.c
drivers/char/drm/i830_drv.c
+1
-0
drivers/char/drm/i830_drv.h
drivers/char/drm/i830_drv.h
+12
-9
drivers/char/drm/radeon.h
drivers/char/drm/radeon.h
+76
-6
drivers/char/drm/radeon_cp.c
drivers/char/drm/radeon_cp.c
+3
-0
drivers/char/drm/radeon_drm.h
drivers/char/drm/radeon_drm.h
+55
-4
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_drv.h
+43
-0
drivers/char/drm/radeon_irq.c
drivers/char/drm/radeon_irq.c
+214
-0
drivers/char/drm/radeon_mem.c
drivers/char/drm/radeon_mem.c
+334
-0
drivers/char/drm/radeon_state.c
drivers/char/drm/radeon_state.c
+60
-10
drivers/ide/ide.c
drivers/ide/ide.c
+1
-1
include/asm-alpha/ide.h
include/asm-alpha/ide.h
+0
-11
include/asm-alpha/rwsem.h
include/asm-alpha/rwsem.h
+6
-4
include/asm-alpha/unistd.h
include/asm-alpha/unistd.h
+12
-0
kernel/exit.c
kernel/exit.c
+6
-1
No files found.
arch/alpha/Makefile
View file @
cd585d2f
...
...
@@ -91,9 +91,9 @@ CFLAGS := $(CFLAGS) -Wa,-mev6
HEAD
:=
arch
/alpha/kernel/head.o
core-y
:
=
arch
/alpha/kernel/
arch
/alpha/mm/
core-$(CONFIG_MATHEMU)
+=
arch
/alpha/math-emu/
built-in.o
libs-y
:=
arch
/alpha/lib
core-y
+
=
arch
/alpha/kernel/
arch
/alpha/mm/
core-$(CONFIG_MATHEMU)
+=
arch
/alpha/math-emu/
libs-y
+=
arch
/alpha/lib/
MAKEBOOT
=
$(MAKE)
-C
arch
/alpha/boot
...
...
arch/alpha/kernel/entry.S
View file @
cd585d2f
...
...
@@ -1119,3 +1119,27 @@ sys_call_table:
.
quad
sys_readahead
.
quad
sys_ni_syscall
/*
380
,
sys_security
*/
.
quad
sys_tkill
.
quad
sys_setxattr
.
quad
sys_lsetxattr
.
quad
sys_fsetxattr
.
quad
sys_getxattr
.
quad
sys_lgetxattr
.
quad
sys_fgetxattr
.
quad
sys_listxattr
.
quad
sys_llistxattr
.
quad
sys_flistxattr
/*
390
*/
.
quad
sys_removexattr
.
quad
sys_lremovexattr
.
quad
sys_fremovexattr
.
quad
sys_futex
.
quad
sys_sched_setaffinity
.
quad
sys_sched_getaffinity
.
quad
sys_ni_syscall
/*
397
,
tux
*/
.
quad
sys_io_setup
.
quad
sys_io_destroy
.
quad
sys_io_getevents
/*
400
*/
.
quad
sys_io_submit
.
quad
sys_io_cancel
.
quad
sys_ni_syscall
/*
403
,
sys_alloc_hugepages
*/
.
quad
sys_ni_syscall
/*
404
,
sys_free_hugepages
*/
.
quad
sys_exit_group
arch/alpha/lib/Makefile
View file @
cd585d2f
...
...
@@ -2,7 +2,7 @@
# Makefile for alpha-specific library files..
#
EXTRA_AFLAGS
:=
$(CFLAGS)
L_TARGET
:=
lib.a
# Many of these routines have implementations tuned for ev6.
# Choose them iff we're targeting ev6 specifically.
...
...
@@ -17,7 +17,7 @@ ifeq ($(CONFIG_ALPHA_EV67),y)
ev67
:=
ev67-
endif
OBJS
=
__divqu.o __remqu.o __divlu.o __remlu.o
\
obj-y
=
__divqu.o __remqu.o __divlu.o __remlu.o
\
udelay.o
\
$(ev6)
memset.o
\
$(ev6)
memcpy.o
\
...
...
@@ -46,12 +46,9 @@ OBJS = __divqu.o __remqu.o __divlu.o __remlu.o \
fpreg.o
\
callback_srm.o srm_puts.o srm_printk.o
ifeq
($(CONFIG_SMP),y)
OBJS
+=
dec_and_lock.o
endif
obj-$(CONFIG_SMP)
+=
dec_and_lock.o
lib.a
:
$(OBJS)
$(AR)
rcs lib.a
$(OBJS)
include
$(TOPDIR)/Rules.make
__divqu.o
:
$(ev6)divide.S
$(CC)
$(AFLAGS)
-DDIV
-c
-o
__divqu.o
$(ev6)
divide.S
...
...
@@ -64,5 +61,3 @@ __divlu.o: $(ev6)divide.S
__remlu.o
:
$(ev6)divide.S
$(CC)
$(AFLAGS)
-DREM
-DINTSIZE
-c
-o
__remlu.o
$(ev6)
divide.S
include
$(TOPDIR)/Rules.make
arch/alpha/math-emu/Makefile
View file @
cd585d2f
...
...
@@ -2,10 +2,8 @@
# Makefile for the FPU instruction emulation.
#
obj-$(CONFIG_MATHEMU)
+=
math-emu.o
math-emu-objs
:=
math.o qrnnd.o
CFLAGS
+=
-I
.
-I
$(TOPDIR)
/include/math-emu
-w
obj-$(CONFIG_MATHEMU)
+=
math.o qrnnd.o
include
$(TOPDIR)/Rules.make
drivers/block/elevator.c
View file @
cd585d2f
...
...
@@ -157,13 +157,20 @@ inline int elv_try_last_merge(request_queue_t *q, struct request **req,
return
ret
;
}
static
int
bio_rq_before
(
struct
bio
*
bio
,
struct
request
*
rq
)
{
if
(
!
kdev_same
(
to_kdev_t
(
bio
->
bi_bdev
->
bd_dev
),
rq
->
rq_dev
))
return
0
;
return
bio
->
bi_sector
<
rq
->
sector
;
}
/*
* elevator_linux starts here
*/
int
elevator_linus_merge
(
request_queue_t
*
q
,
struct
request
**
req
,
struct
bio
*
bio
)
{
struct
list_head
*
entry
;
struct
list_head
*
entry
,
*
good
;
struct
request
*
__rq
;
int
ret
;
...
...
@@ -171,6 +178,7 @@ int elevator_linus_merge(request_queue_t *q, struct request **req,
return
ret
;
entry
=
&
q
->
queue_head
;
good
=
&
q
->
queue_head
;
ret
=
ELEVATOR_NO_MERGE
;
while
((
entry
=
entry
->
prev
)
!=
&
q
->
queue_head
)
{
__rq
=
list_entry_rq
(
entry
);
...
...
@@ -178,37 +186,31 @@ int elevator_linus_merge(request_queue_t *q, struct request **req,
if
(
__rq
->
flags
&
(
REQ_BARRIER
|
REQ_STARTED
))
break
;
if
(
!
(
__rq
->
flags
&
REQ_CMD
))
continue
;
if
(
elv_linus_sequence
(
__rq
)
<
bio_sectors
(
bio
))
break
;
if
(
!*
req
&&
bio_rq_in_between
(
bio
,
__rq
,
&
q
->
queue_head
))
*
req
=
__rq
;
if
(
bio_data_dir
(
bio
)
!=
rq_data_dir
(
__rq
))
{
if
(
bio_data_dir
(
bio
)
==
WRITE
)
break
;
good
=
entry
->
prev
;
continue
;
}
if
((
ret
=
elv_try_merge
(
__rq
,
bio
)))
{
if
(
ret
==
ELEVATOR_FRONT_MERGE
)
elv_linus_sequence
(
__rq
)
-=
bio_sectors
(
bio
);
ret
=
elv_try_merge
(
__rq
,
bio
);
if
(
ret
)
{
*
req
=
__rq
;
q
->
last_merge
=
&
__rq
->
queuelist
;
break
;
}
return
ret
;
}
/*
* if *req, it's either a seek or merge in the middle of the queue
*/
if
(
*
req
)
{
struct
list_head
*
entry
=
&
(
*
req
)
->
queuelist
;
int
cost
=
ret
?
1
:
ELV_LINUS_SEEK_COST
;
if
(
bio_rq_before
(
bio
,
__rq
))
good
=
entry
->
prev
;
while
((
entry
=
entry
->
next
)
!=
&
q
->
queue_head
)
{
__rq
=
list_entry_rq
(
entry
);
elv_linus_sequence
(
__rq
)
-=
cost
;
}
}
return
ret
;
if
(
good
!=
&
q
->
queue_head
)
*
req
=
list_entry_rq
(
good
);
return
ELEVATOR_NO_MERGE
;
}
void
elevator_linus_merge_req
(
request_queue_t
*
q
,
struct
request
*
req
,
...
...
drivers/char/drm/Makefile
View file @
cd585d2f
...
...
@@ -8,7 +8,7 @@ r128-objs := r128_drv.o r128_cce.o r128_state.o
mga-objs
:=
mga_drv.o mga_dma.o mga_state.o mga_warp.o
i810-objs
:=
i810_drv.o i810_dma.o
i830-objs
:=
i830_drv.o i830_dma.o
radeon-objs
:=
radeon_drv.o radeon_cp.o radeon_state.o
radeon-objs
:=
radeon_drv.o radeon_cp.o radeon_state.o
radeon_mem.o radeon_irq.o
ffb-objs
:=
ffb_drv.o ffb_context.o
obj-$(CONFIG_DRM_GAMMA)
+=
gamma.o
...
...
drivers/char/drm/drmP.h
View file @
cd585d2f
...
...
@@ -165,7 +165,7 @@
#define pte_unmap(pte)
#endif
#if LINUX_VERSION_CODE <
0x020413
/* KERNEL_VERSION(2,4,19) */
#if LINUX_VERSION_CODE <
KERNEL_VERSION(2,4,19)
static
inline
struct
page
*
vmalloc_to_page
(
void
*
vmalloc_addr
)
{
unsigned
long
addr
=
(
unsigned
long
)
vmalloc_addr
;
...
...
@@ -190,7 +190,7 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr)
}
#endif
#if LINUX_VERSION_CODE <
0x020500
#if LINUX_VERSION_CODE <
KERNEL_VERSION(2,5,0)
#define DRM_RPR_ARG(vma)
#else
#define DRM_RPR_ARG(vma) vma,
...
...
@@ -597,7 +597,7 @@ typedef struct drm_device {
#endif
struct
pci_dev
*
pdev
;
#ifdef __alpha__
#if LINUX_VERSION_CODE <
0x020403
#if LINUX_VERSION_CODE <
KERNEL_VERSION(2,4,3)
struct
pci_controler
*
hose
;
#else
struct
pci_controller
*
hose
;
...
...
drivers/char/drm/drm_bufs.h
View file @
cd585d2f
...
...
@@ -137,6 +137,7 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
}
map
->
offset
=
(
unsigned
long
)
map
->
handle
;
if
(
map
->
flags
&
_DRM_CONTAINS_LOCK
)
{
dev
->
sigdata
.
lock
=
dev
->
lock
.
hw_lock
=
map
->
handle
;
/* Pointer to lock */
}
break
;
...
...
drivers/char/drm/drm_drv.h
View file @
cd585d2f
...
...
@@ -306,7 +306,7 @@ static int DRM(setup)( drm_device_t *dev )
dev
->
map_count
=
0
;
dev
->
vmalist
=
NULL
;
dev
->
lock
.
hw_lock
=
NULL
;
dev
->
sigdata
.
lock
=
dev
->
lock
.
hw_lock
=
NULL
;
init_waitqueue_head
(
&
dev
->
lock
.
lock_queue
);
dev
->
queue_count
=
0
;
dev
->
queue_reserved
=
0
;
...
...
@@ -491,7 +491,7 @@ static int DRM(takedown)( drm_device_t *dev )
DRM
(
dma_takedown
)(
dev
);
#endif
if
(
dev
->
lock
.
hw_lock
)
{
dev
->
lock
.
hw_lock
=
NULL
;
/* SHM removed */
dev
->
sigdata
.
lock
=
dev
->
lock
.
hw_lock
=
NULL
;
/* SHM removed */
dev
->
lock
.
pid
=
0
;
wake_up_interruptible
(
&
dev
->
lock
.
lock_queue
);
}
...
...
drivers/char/drm/drm_lock.h
View file @
cd585d2f
...
...
@@ -237,7 +237,7 @@ int DRM(notifier)(void *priv)
/* Allow signal delivery if lock isn't held */
if
(
!
_DRM_LOCK_IS_HELD
(
s
->
lock
->
lock
)
if
(
!
s
->
lock
||
!
_DRM_LOCK_IS_HELD
(
s
->
lock
->
lock
)
||
_DRM_LOCKING_CONTEXT
(
s
->
lock
->
lock
)
!=
s
->
context
)
return
1
;
/* Otherwise, set flag to force call to
...
...
drivers/char/drm/drm_os_linux.h
View file @
cd585d2f
...
...
@@ -16,6 +16,9 @@
#define DRM_DEVICE drm_file_t *priv = filp->private_data; \
drm_device_t *dev = priv->dev
#define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs
#define DRM_TASKQUEUE_ARGS void *arg
/* For data going from/to the kernel through the ioctl argument */
#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
if ( copy_from_user(&arg1, arg2, arg3) ) \
...
...
drivers/char/drm/i830.h
View file @
cd585d2f
...
...
@@ -45,11 +45,11 @@
#define DRIVER_NAME "i830"
#define DRIVER_DESC "Intel 830M"
#define DRIVER_DATE "200
11004
"
#define DRIVER_DATE "200
20828
"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 2
#define DRIVER_PATCHLEVEL
0
#define DRIVER_PATCHLEVEL
1
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)] = { i830_dma_init, 1, 1 }, \
...
...
@@ -87,50 +87,10 @@
i830_dma_quiescent( dev ); \
} while (0)
#define __HAVE_DMA_IRQ 1
#define __HAVE_DMA_IRQ_BH 1
#define __HAVE_SHARED_IRQ 1
#define DRIVER_PREINSTALL() do { \
drm_i830_private_t *dev_priv = \
(drm_i830_private_t *)dev->dev_private; \
u16 tmp; \
tmp = I830_READ16( I830REG_HWSTAM ); \
tmp = tmp & 0x6000; \
I830_WRITE16( I830REG_HWSTAM, tmp ); \
\
tmp = I830_READ16( I830REG_INT_MASK_R ); \
tmp = tmp & 0x6000;
/* Unmask interrupts */
\
I830_WRITE16( I830REG_INT_MASK_R, tmp ); \
tmp = I830_READ16( I830REG_INT_ENABLE_R ); \
tmp = tmp & 0x6000;
/* Disable all interrupts */
\
I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \
} while (0)
#define DRIVER_POSTINSTALL() do { \
drm_i830_private_t *dev_priv = \
(drm_i830_private_t *)dev->dev_private; \
u16 tmp; \
tmp = I830_READ16( I830REG_INT_ENABLE_R ); \
tmp = tmp & 0x6000; \
tmp = tmp | 0x0003;
/* Enable bp & user interrupts */
\
I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \
} while (0)
#define DRIVER_UNINSTALL() do { \
drm_i830_private_t *dev_priv = \
(drm_i830_private_t *)dev->dev_private; \
u16 tmp; \
if ( dev_priv ) { \
tmp = I830_READ16( I830REG_INT_IDENTITY_R ); \
tmp = tmp & ~(0x6000);
/* Clear all interrupts */
\
if ( tmp != 0 ) \
I830_WRITE16( I830REG_INT_IDENTITY_R, tmp ); \
\
tmp = I830_READ16( I830REG_INT_ENABLE_R ); \
tmp = tmp & 0x6000;
/* Disable all interrupts */
\
I830_WRITE16( I830REG_INT_ENABLE_R, tmp ); \
} \
} while (0)
/* Don't need an irq any more. The template code will make sure that
* a noop stub is generated for compatibility.
*/
#define __HAVE_DMA_IRQ 0
/* Buffer customization:
*/
...
...
drivers/char/drm/i830_dma.c
View file @
cd585d2f
...
...
@@ -26,7 +26,7 @@
*
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
* Jeff Hartmann <jhartmann@valinux.com>
*
Keith Whitwell <keithw@valinux
.com>
*
Keith Whitwell <keith@tungstengraphics
.com>
* Abraham vd Merwe <abraham@2d3d.co.za>
*
*/
...
...
@@ -40,9 +40,10 @@
#include <linux/interrupt.h>
/* For task queue support */
#include <linux/delay.h>
/* in case we don't have a 2.3.99-pre6 kernel or later: */
#ifndef VM_DONTCOPY
#define VM_DONTCOPY 0
#ifdef DO_MUNMAP_4_ARGS
#define DO_MUNMAP(m, a, l) do_munmap(m, a, l, 1)
#else
#define DO_MUNMAP(m, a, l) do_munmap(m, a, l)
#endif
#define I830_BUF_FREE 2
...
...
@@ -54,26 +55,24 @@
#define RING_LOCALS unsigned int outring, ringmask; volatile char *virt;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
#define down_write down
#define up_write up
#endif
#define DO_IDLE_WORKAROUND() \
do { \
int _head; \
int _tail; \
do { \
_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; \
_tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; \
udelay(10); \
} while(_head != _tail); \
} while(0)
#ifndef LockPage
#define LockPage(page) set_bit(PG_locked, &(page)->flags)
#endif
#ifndef UnlockPage
#define UnlockPage(page) unlock_page(page)
#endif
#define I830_
SYNC_WORKAROUND
0
#define I830_
VERBOSE
0
#define BEGIN_LP_RING(n) do { \
if (I830_VERBOSE) \
DRM_DEBUG
("BEGIN_LP_RING(%d) in %s\n", \
printk
("BEGIN_LP_RING(%d) in %s\n", \
n, __FUNCTION__); \
if (I830_SYNC_WORKAROUND) \
DO_IDLE_WORKAROUND(); \
if (dev_priv->ring.space < n*4) \
i830_wait_ring(dev, n*4); \
dev_priv->ring.space -= n*4; \
...
...
@@ -83,13 +82,13 @@ do { \
} while (0)
#define ADVANCE_LP_RING() do { \
if (I830_VERBOSE)
DRM_DEBUG("ADVANCE_LP_RING\n"
); \
if (I830_VERBOSE)
printk("ADVANCE_LP_RING %x\n", outring
); \
dev_priv->ring.tail = outring; \
I830_WRITE(LP_RING + RING_TAIL, outring); \
} while(0)
#define OUT_RING(n) do { \
if (I830_VERBOSE)
DRM_DEBUG
(" OUT_RING %x\n", (int)(n)); \
if (I830_VERBOSE)
printk
(" OUT_RING %x\n", (int)(n)); \
*(volatile unsigned int *)(virt + outring) = n; \
outring += 4; \
outring &= ringmask; \
...
...
@@ -201,12 +200,7 @@ static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
if
(
buf_priv
->
currently_mapped
==
I830_BUF_MAPPED
)
return
-
EINVAL
;
if
(
VM_DONTCOPY
!=
0
)
{
#if LINUX_VERSION_CODE <= 0x020402
down
(
&
current
->
mm
->
mmap_sem
);
#else
down_write
(
&
current
->
mm
->
mmap_sem
);
#endif
old_fops
=
filp
->
f_op
;
filp
->
f_op
=
&
i830_buffer_fops
;
dev_priv
->
mmap_buffer
=
buf
;
...
...
@@ -218,19 +212,12 @@ static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
filp
->
f_op
=
old_fops
;
if
((
unsigned
long
)
buf_priv
->
virtual
>
-
1024UL
)
{
/* Real error */
DRM_DEBUG
(
"mmap error
\n
"
);
DRM_ERROR
(
"mmap error
\n
"
);
retcode
=
(
signed
int
)
buf_priv
->
virtual
;
buf_priv
->
virtual
=
0
;
}
#if LINUX_VERSION_CODE <= 0x020402
up
(
&
current
->
mm
->
mmap_sem
);
#else
up_write
(
&
current
->
mm
->
mmap_sem
);
#endif
}
else
{
buf_priv
->
virtual
=
buf_priv
->
kernel_virtual
;
buf_priv
->
currently_mapped
=
I830_BUF_MAPPED
;
}
return
retcode
;
}
...
...
@@ -239,25 +226,15 @@ static int i830_unmap_buffer(drm_buf_t *buf)
drm_i830_buf_priv_t
*
buf_priv
=
buf
->
dev_private
;
int
retcode
=
0
;
if
(
VM_DONTCOPY
!=
0
)
{
if
(
buf_priv
->
currently_mapped
!=
I830_BUF_MAPPED
)
return
-
EINVAL
;
#if LINUX_VERSION_CODE <= 0x020402
down
(
&
current
->
mm
->
mmap_sem
);
#else
down_write
(
&
current
->
mm
->
mmap_sem
);
#endif
retcode
=
do_munmap
(
current
->
mm
,
down_write
(
&
current
->
mm
->
mmap_sem
);
retcode
=
DO_MUNMAP
(
current
->
mm
,
(
unsigned
long
)
buf_priv
->
virtual
,
(
size_t
)
buf
->
total
);
up_write
(
&
current
->
mm
->
mmap_sem
);
#if LINUX_VERSION_CODE <= 0x020402
up
(
&
current
->
mm
->
mmap_sem
);
#else
up_write
(
&
current
->
mm
->
mmap_sem
);
#endif
}
buf_priv
->
currently_mapped
=
I830_BUF_UNMAPPED
;
buf_priv
->
virtual
=
0
;
...
...
@@ -275,14 +252,14 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
buf
=
i830_freelist_get
(
dev
);
if
(
!
buf
)
{
retcode
=
-
ENOMEM
;
DRM_
DEBUG
(
"retcode=%d
\n
"
,
retcode
);
DRM_
ERROR
(
"retcode=%d
\n
"
,
retcode
);
return
retcode
;
}
retcode
=
i830_map_buffer
(
buf
,
filp
);
if
(
retcode
)
{
i830_freelist_put
(
dev
,
buf
);
DRM_
DEBUG
(
"mapbuf failed, retcode %d
\n
"
,
retcode
);
DRM_
ERROR
(
"mapbuf failed, retcode %d
\n
"
,
retcode
);
return
retcode
;
}
buf
->
pid
=
priv
->
pid
;
...
...
@@ -303,32 +280,17 @@ static unsigned long i830_alloc_page(drm_device_t *dev)
if
(
address
==
0UL
)
return
0
;
#if LINUX_VERSION_CODE < 0x020409
atomic_inc
(
&
virt_to_page
(
address
)
->
count
);
set_bit
(
PG_locked
,
&
virt_to_page
(
address
)
->
flags
);
#else
get_page
(
virt_to_page
(
address
));
#if LINUX_VERSION_CODE < 0x020500
LockPage
(
virt_to_page
(
address
));
#else
SetPageLocked
(
virt_to_page
(
address
));
#endif
#endif
return
address
;
}
static
void
i830_free_page
(
drm_device_t
*
dev
,
unsigned
long
page
)
{
if
(
page
)
{
#if LINUX_VERSION_CODE < 0x020409
atomic_dec
(
&
virt_to_page
(
page
)
->
count
);
clear_bit
(
PG_locked
,
&
virt_to_page
(
page
)
->
flags
);
wake_up
(
&
virt_to_page
(
page
)
->
wait
);
#else
struct
page
*
p
=
virt_to_page
(
page
);
put_page
(
p
);
unlock_page
(
p
);
#endif
UnlockPage
(
p
);
free_page
(
page
);
}
}
...
...
@@ -384,7 +346,7 @@ static int i830_wait_ring(drm_device_t *dev, int n)
}
iters
++
;
if
(
(
signed
)(
end
-
jiffies
)
<=
0
)
{
if
(
time_before
(
end
,
jiffies
)
)
{
DRM_ERROR
(
"space: %d wanted %d
\n
"
,
ring
->
space
,
n
);
DRM_ERROR
(
"lockup
\n
"
);
goto
out_wait_ring
;
...
...
@@ -402,7 +364,7 @@ static void i830_kernel_lost_context(drm_device_t *dev)
drm_i830_ring_buffer_t
*
ring
=
&
(
dev_priv
->
ring
);
ring
->
head
=
I830_READ
(
LP_RING
+
RING_HEAD
)
&
HEAD_ADDR
;
ring
->
tail
=
I830_READ
(
LP_RING
+
RING_TAIL
);
ring
->
tail
=
I830_READ
(
LP_RING
+
RING_TAIL
)
&
TAIL_ADDR
;
ring
->
space
=
ring
->
head
-
(
ring
->
tail
+
8
);
if
(
ring
->
space
<
0
)
ring
->
space
+=
ring
->
Size
;
}
...
...
@@ -478,9 +440,6 @@ static int i830_dma_initialize(drm_device_t *dev,
((
u8
*
)
dev_priv
->
sarea_map
->
handle
+
init
->
sarea_priv_offset
);
atomic_set
(
&
dev_priv
->
flush_done
,
0
);
init_waitqueue_head
(
&
dev_priv
->
flush_queue
);
dev_priv
->
ring
.
Start
=
init
->
ring_start
;
dev_priv
->
ring
.
End
=
init
->
ring_end
;
dev_priv
->
ring
.
Size
=
init
->
ring_size
;
...
...
@@ -504,11 +463,17 @@ static int i830_dma_initialize(drm_device_t *dev,
dev_priv
->
pitch
=
init
->
pitch
;
dev_priv
->
back_offset
=
init
->
back_offset
;
dev_priv
->
depth_offset
=
init
->
depth_offset
;
dev_priv
->
front_offset
=
init
->
front_offset
;
dev_priv
->
front_di1
=
init
->
front_offset
|
init
->
pitch_bits
;
dev_priv
->
back_di1
=
init
->
back_offset
|
init
->
pitch_bits
;
dev_priv
->
zi1
=
init
->
depth_offset
|
init
->
pitch_bits
;
DRM_DEBUG
(
"front_di1 %x
\n
"
,
dev_priv
->
front_di1
);
DRM_DEBUG
(
"back_offset %x
\n
"
,
dev_priv
->
back_offset
);
DRM_DEBUG
(
"back_di1 %x
\n
"
,
dev_priv
->
back_di1
);
DRM_DEBUG
(
"pitch_bits %x
\n
"
,
init
->
pitch_bits
);
dev_priv
->
cpp
=
init
->
cpp
;
/* We are using seperate values as placeholders for mechanisms for
* private backbuffer/depthbuffer usage.
...
...
@@ -574,37 +539,56 @@ int i830_dma_init(struct inode *inode, struct file *filp,
return
retcode
;
}
#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
#define ST1_ENABLE (1<<16)
#define ST1_MASK (0xffff)
/* Most efficient way to verify state for the i830 is as it is
* emitted. Non-conformant state is silently dropped.
*
* Use 'volatile' & local var tmp to force the emitted values to be
* identical to the verified ones.
*/
static
void
i830EmitContextVerified
(
drm_device_t
*
dev
,
volatile
unsigned
int
*
code
)
unsigned
int
*
code
)
{
drm_i830_private_t
*
dev_priv
=
dev
->
dev_private
;
int
i
,
j
=
0
;
unsigned
int
tmp
;
RING_LOCALS
;
BEGIN_LP_RING
(
I830_CTX_SETUP_SIZE
);
for
(
i
=
0
;
i
<
I830_CTX_SETUP_SIZE
;
i
++
)
{
tmp
=
code
[
i
];
BEGIN_LP_RING
(
I830_CTX_SETUP_SIZE
+
2
);
OUT_RING
(
GFX_OP_STIPPLE
);
OUT_RING
(
0
);
#if 0
if ((tmp & (7<<29)) == (3<<29) &&
for
(
i
=
0
;
i
<
I830_CTXREG_BLENDCOLR0
;
i
++
)
{
tmp
=
code
[
i
];
if
((
tmp
&
(
7
<<
29
))
==
CMD_3D
&&
(
tmp
&
(
0x1f
<<
24
))
<
(
0x1d
<<
24
))
{
OUT_RING
(
tmp
);
j
++
;
}
else
{
printk
("Skipping %d\n", i);
DRM_ERROR
(
"Skipping %d
\n
"
,
i
);
}
#else
}
OUT_RING
(
STATE3D_CONST_BLEND_COLOR_CMD
);
OUT_RING
(
code
[
I830_CTXREG_BLENDCOLR
]
);
j
+=
2
;
for
(
i
=
I830_CTXREG_VF
;
i
<
I830_CTXREG_MCSB0
;
i
++
)
{
tmp
=
code
[
i
];
if
((
tmp
&
(
7
<<
29
))
==
CMD_3D
&&
(
tmp
&
(
0x1f
<<
24
))
<
(
0x1d
<<
24
))
{
OUT_RING
(
tmp
);
j
++
;
#endif
}
else
{
DRM_ERROR
(
"Skipping %d
\n
"
,
i
);
}
}
OUT_RING
(
STATE3D_MAP_COORD_SETBIND_CMD
);
OUT_RING
(
code
[
I830_CTXREG_MCSB1
]
);
j
+=
2
;
if
(
j
&
1
)
OUT_RING
(
0
);
...
...
@@ -650,6 +634,9 @@ static void i830EmitTexBlendVerified( drm_device_t *dev,
unsigned
int
tmp
;
RING_LOCALS
;
if
(
!
num
)
return
;
BEGIN_LP_RING
(
num
);
for
(
i
=
0
;
i
<
num
;
i
++
)
{
...
...
@@ -723,7 +710,7 @@ static void i830EmitDestVerified( drm_device_t *dev,
BUF_3D_PITCH
(
dev_priv
->
depth_pitch
*
dev_priv
->
cpp
));
OUT_RING
(
dev_priv
->
zi1
);
}
else
{
DRM_
DEBUG
(
"bad di1 %x (allow %x or %x)
\n
"
,
DRM_
ERROR
(
"bad di1 %x (allow %x or %x)
\n
"
,
tmp
,
dev_priv
->
front_di1
,
dev_priv
->
back_di1
);
}
...
...
@@ -745,7 +732,7 @@ static void i830EmitDestVerified( drm_device_t *dev,
if
((
tmp
&
~
0x3
)
==
GFX_OP_SCISSOR_ENABLE
)
{
OUT_RING
(
tmp
);
}
else
{
DRM_
DEBUG
(
"bad scissor enable
\n
"
);
DRM_
ERROR
(
"bad scissor enable
\n
"
);
OUT_RING
(
0
);
}
...
...
@@ -865,7 +852,7 @@ static void i830_dma_dispatch_clear( drm_device_t *dev, int flags,
OUT_RING
(
BR13
);
OUT_RING
(
(
pbox
->
y1
<<
16
)
|
pbox
->
x1
);
OUT_RING
(
(
pbox
->
y2
<<
16
)
|
pbox
->
x2
);
OUT_RING
(
0
);
OUT_RING
(
dev_priv
->
front_offset
);
OUT_RING
(
clear_color
);
ADVANCE_LP_RING
();
}
...
...
@@ -953,7 +940,7 @@ static void i830_dma_dispatch_swap( drm_device_t *dev )
OUT_RING
(
(
pbox
->
y2
<<
16
)
|
pbox
->
x2
);
OUT_RING
(
0
/* front ofs always zero */
);
OUT_RING
(
dev_priv
->
front_offset
);
OUT_RING
(
(
pbox
->
y1
<<
16
)
|
pbox
->
x1
);
...
...
@@ -993,7 +980,7 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
}
}
if
(
used
>
4
*
102
4
)
if
(
used
>
4
*
102
3
)
used
=
0
;
if
(
sarea_priv
->
dirty
)
...
...
@@ -1010,12 +997,17 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
DRM_DEBUG
(
"start + used - 4 : %ld
\n
"
,
start
+
used
-
4
);
if
(
buf_priv
->
currently_mapped
==
I830_BUF_MAPPED
)
{
*
(
u32
*
)
buf_priv
->
virtual
=
(
GFX_OP_PRIMITIVE
|
u32
*
vp
=
buf_priv
->
virtual
;
vp
[
0
]
=
(
GFX_OP_PRIMITIVE
|
sarea_priv
->
vertex_prim
|
((
used
/
4
)
-
2
));
vp
[
used
/
4
]
=
MI_BATCH_BUFFER_END
;
used
+=
4
;
if
(
used
&
4
)
{
*
(
u32
*
)((
u32
)
buf_priv
->
virtual
+
used
)
=
0
;
vp
[
used
/
4
]
=
0
;
used
+=
4
;
}
...
...
@@ -1035,163 +1027,66 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
ADVANCE_LP_RING
();
}
BEGIN_LP_RING
(
4
);
OUT_RING
(
MI_BATCH_BUFFER
);
BEGIN_LP_RING
(
2
);
OUT_RING
(
MI_BATCH_BUFFER_START
|
(
2
<<
6
)
);
OUT_RING
(
start
|
MI_BATCH_NON_SECURE
);
OUT_RING
(
start
+
used
-
4
);
OUT_RING
(
0
);
ADVANCE_LP_RING
();
}
while
(
++
i
<
nbox
);
}
BEGIN_LP_RING
(
10
);
if
(
discard
)
{
dev_priv
->
counter
++
;
(
void
)
cmpxchg
(
buf_priv
->
in_use
,
I830_BUF_CLIENT
,
I830_BUF_HARDWARE
);
BEGIN_LP_RING
(
8
);
OUT_RING
(
CMD_STORE_DWORD_IDX
);
OUT_RING
(
20
);
OUT_RING
(
dev_priv
->
counter
);
OUT_RING
(
0
);
if
(
discard
)
{
OUT_RING
(
CMD_STORE_DWORD_IDX
);
OUT_RING
(
buf_priv
->
my_use_idx
);
OUT_RING
(
I830_BUF_FREE
);
OUT_RING
(
0
);
}
OUT_RING
(
CMD_REPORT_HEAD
);
OUT_RING
(
0
);
ADVANCE_LP_RING
();
}
}
/* Interrupts are only for flushing */
void
i830_dma_service
(
int
irq
,
void
*
device
,
struct
pt_regs
*
regs
)
{
drm_device_t
*
dev
=
(
drm_device_t
*
)
device
;
drm_i830_private_t
*
dev_priv
=
(
drm_i830_private_t
*
)
dev
->
dev_private
;
u16
temp
;
temp
=
I830_READ16
(
I830REG_INT_IDENTITY_R
);
temp
=
temp
&
~
(
0x6000
);
if
(
temp
!=
0
)
I830_WRITE16
(
I830REG_INT_IDENTITY_R
,
temp
);
/* Clear all interrupts */
else
return
;
queue_task
(
&
dev
->
tq
,
&
tq_immediate
);
mark_bh
(
IMMEDIATE_BH
);
}
void
DRM
(
dma_immediate_bh
)(
void
*
device
)
{
drm_device_t
*
dev
=
(
drm_device_t
*
)
device
;
drm_i830_private_t
*
dev_priv
=
(
drm_i830_private_t
*
)
dev
->
dev_private
;
atomic_set
(
&
dev_priv
->
flush_done
,
1
);
wake_up_interruptible
(
&
dev_priv
->
flush_queue
);
}
static
inline
void
i830_dma_emit_flush
(
drm_device_t
*
dev
)
void
i830_dma_quiescent
(
drm_device_t
*
dev
)
{
drm_i830_private_t
*
dev_priv
=
dev
->
dev_private
;
RING_LOCALS
;
i830_kernel_lost_context
(
dev
);
BEGIN_LP_RING
(
2
);
BEGIN_LP_RING
(
4
);
OUT_RING
(
INST_PARSER_CLIENT
|
INST_OP_FLUSH
|
INST_FLUSH_MAP_CACHE
);
OUT_RING
(
CMD_REPORT_HEAD
);
OUT_RING
(
GFX_OP_USER_INTERRUPT
);
OUT_RING
(
0
);
OUT_RING
(
0
);
ADVANCE_LP_RING
();
i830_wait_ring
(
dev
,
dev_priv
->
ring
.
Size
-
8
);
atomic_set
(
&
dev_priv
->
flush_done
,
1
);
wake_up_interruptible
(
&
dev_priv
->
flush_queue
);
}
static
in
line
void
i830_dma_quiescent_emit
(
drm_device_t
*
dev
)
static
in
t
i830_flush_queue
(
drm_device_t
*
dev
)
{
drm_i830_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_device_dma_t
*
dma
=
dev
->
dma
;
int
i
,
ret
=
0
;
RING_LOCALS
;
i830_kernel_lost_context
(
dev
);
BEGIN_LP_RING
(
4
);
OUT_RING
(
INST_PARSER_CLIENT
|
INST_OP_FLUSH
|
INST_FLUSH_MAP_CACHE
);
BEGIN_LP_RING
(
2
);
OUT_RING
(
CMD_REPORT_HEAD
);
OUT_RING
(
0
);
OUT_RING
(
GFX_OP_USER_INTERRUPT
);
ADVANCE_LP_RING
();
i830_wait_ring
(
dev
,
dev_priv
->
ring
.
Size
-
8
);
atomic_set
(
&
dev_priv
->
flush_done
,
1
);
wake_up_interruptible
(
&
dev_priv
->
flush_queue
);
}
void
i830_dma_quiescent
(
drm_device_t
*
dev
)
{
DECLARE_WAITQUEUE
(
entry
,
current
);
drm_i830_private_t
*
dev_priv
=
(
drm_i830_private_t
*
)
dev
->
dev_private
;
unsigned
long
end
;
if
(
dev_priv
==
NULL
)
{
return
;
}
atomic_set
(
&
dev_priv
->
flush_done
,
0
);
add_wait_queue
(
&
dev_priv
->
flush_queue
,
&
entry
);
end
=
jiffies
+
(
HZ
*
3
);
for
(;;)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
i830_dma_quiescent_emit
(
dev
);
if
(
atomic_read
(
&
dev_priv
->
flush_done
)
==
1
)
break
;
if
((
signed
)(
end
-
jiffies
)
<=
0
)
{
DRM_ERROR
(
"lockup
\n
"
);
break
;
}
schedule_timeout
(
HZ
*
3
);
if
(
signal_pending
(
current
))
{
break
;
}
}
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
&
dev_priv
->
flush_queue
,
&
entry
);
return
;
}
static
int
i830_flush_queue
(
drm_device_t
*
dev
)
{
DECLARE_WAITQUEUE
(
entry
,
current
);
drm_i830_private_t
*
dev_priv
=
(
drm_i830_private_t
*
)
dev
->
dev_private
;
drm_device_dma_t
*
dma
=
dev
->
dma
;
unsigned
long
end
;
int
i
,
ret
=
0
;
if
(
dev_priv
==
NULL
)
{
return
0
;
}
atomic_set
(
&
dev_priv
->
flush_done
,
0
);
add_wait_queue
(
&
dev_priv
->
flush_queue
,
&
entry
);
end
=
jiffies
+
(
HZ
*
3
);
for
(;;)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
i830_dma_emit_flush
(
dev
);
if
(
atomic_read
(
&
dev_priv
->
flush_done
)
==
1
)
break
;
if
((
signed
)(
end
-
jiffies
)
<=
0
)
{
DRM_ERROR
(
"lockup
\n
"
);
break
;
}
schedule_timeout
(
HZ
*
3
);
if
(
signal_pending
(
current
))
{
ret
=
-
EINTR
;
/* Can't restart */
break
;
}
}
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
&
dev_priv
->
flush_queue
,
&
entry
);
for
(
i
=
0
;
i
<
dma
->
buf_count
;
i
++
)
{
drm_buf_t
*
buf
=
dma
->
buflist
[
i
];
...
...
@@ -1203,7 +1098,7 @@ static int i830_flush_queue(drm_device_t *dev)
if
(
used
==
I830_BUF_HARDWARE
)
DRM_DEBUG
(
"reclaimed from HARDWARE
\n
"
);
if
(
used
==
I830_BUF_CLIENT
)
DRM_DEBUG
(
"still on client
HARDWARE
\n
"
);
DRM_DEBUG
(
"still on client
\n
"
);
}
return
ret
;
...
...
@@ -1243,7 +1138,6 @@ int i830_flush_ioctl(struct inode *inode, struct file *filp,
drm_file_t
*
priv
=
filp
->
private_data
;
drm_device_t
*
dev
=
priv
->
dev
;
DRM_DEBUG
(
"i830_flush_ioctl
\n
"
);
if
(
!
_DRM_LOCK_IS_HELD
(
dev
->
lock
.
hw_lock
->
lock
))
{
DRM_ERROR
(
"i830_flush_ioctl called without lock held
\n
"
);
return
-
EINVAL
;
...
...
@@ -1381,46 +1275,17 @@ int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
return
retcode
;
}
int
i830_copybuf
(
struct
inode
*
inode
,
struct
file
*
filp
,
unsigned
int
cmd
,
int
i830_copybuf
(
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_i830_copy_t
d
;
drm_i830_private_t
*
dev_priv
=
(
drm_i830_private_t
*
)
dev
->
dev_private
;
u32
*
hw_status
=
(
u32
*
)
dev_priv
->
hw_status_page
;
drm_i830_sarea_t
*
sarea_priv
=
(
drm_i830_sarea_t
*
)
dev_priv
->
sarea_priv
;
drm_buf_t
*
buf
;
drm_i830_buf_priv_t
*
buf_priv
;
drm_device_dma_t
*
dma
=
dev
->
dma
;
if
(
!
_DRM_LOCK_IS_HELD
(
dev
->
lock
.
hw_lock
->
lock
))
{
DRM_ERROR
(
"i830_dma called without lock held
\n
"
);
return
-
EINVAL
;
}
if
(
copy_from_user
(
&
d
,
(
drm_i830_copy_t
*
)
arg
,
sizeof
(
d
)))
return
-
EFAULT
;
if
(
d
.
idx
<
0
||
d
.
idx
>
dma
->
buf_count
)
return
-
EINVAL
;
buf
=
dma
->
buflist
[
d
.
idx
];
buf_priv
=
buf
->
dev_private
;
if
(
buf_priv
->
currently_mapped
!=
I830_BUF_MAPPED
)
return
-
EPERM
;
if
(
d
.
used
<
0
||
d
.
used
>
buf
->
total
)
return
-
EINVAL
;
if
(
copy_from_user
(
buf_priv
->
virtual
,
d
.
address
,
d
.
used
))
return
-
EFAULT
;
sarea_priv
->
last_dispatch
=
(
int
)
hw_status
[
5
];
/* Never copy - 2.4.x doesn't need it */
return
0
;
}
int
i830_docopy
(
struct
inode
*
inode
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
if
(
VM_DONTCOPY
==
0
)
return
1
;
return
0
;
}
drivers/char/drm/i830_drv.c
View file @
cd585d2f
...
...
@@ -29,6 +29,7 @@
* Jeff Hartmann <jhartmann@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Abraham vd Merwe <abraham@2d3d.co.za>
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include <linux/config.h>
...
...
drivers/char/drm/i830_drv.h
View file @
cd585d2f
...
...
@@ -64,14 +64,13 @@ typedef struct drm_i830_private {
unsigned
long
hw_status_page
;
unsigned
long
counter
;
atomic_t
flush_done
;
wait_queue_head_t
flush_queue
;
/* Processes waiting until flush */
drm_buf_t
*
mmap_buffer
;
u32
front_di1
,
back_di1
,
zi1
;
int
back_offset
;
int
depth_offset
;
int
front_offset
;
int
w
,
h
;
int
pitch
;
int
back_pitch
;
...
...
@@ -107,14 +106,13 @@ extern int i830_swap_bufs(struct inode *inode, struct file *filp,
extern
int
i830_clear_bufs
(
struct
inode
*
inode
,
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
);
#define I830_VERBOSE 0
#define I830_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle)
#define I830_ADDR(reg) (I830_BASE(reg) + reg)
#define I830_DEREF(reg) *(__volatile__ int *)I830_ADDR(reg)
#define I830_READ(reg)
I830_DEREF(reg
)
#define I830_WRITE(reg,val)
do { I830_DEREF(reg) = val; } while (0
)
#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)
...
...
@@ -143,15 +141,15 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define LP_RING 0x2030
#define HP_RING 0x2040
#define RING_TAIL 0x00
#define TAIL_ADDR 0x00
0
FFFF8
#define TAIL_ADDR 0x00
1
FFFF8
#define RING_HEAD 0x04
#define HEAD_WRAP_COUNT 0xFFE00000
#define HEAD_WRAP_ONE 0x00200000
#define HEAD_ADDR 0x001FFFFC
#define RING_START 0x08
#define START_ADDR 0x0
0FFFFF8
#define START_ADDR 0x0
xFFFFF000
#define RING_LEN 0x0C
#define RING_NR_PAGES 0x00
0
FF000
#define RING_NR_PAGES 0x00
1
FF000
#define RING_REPORT_MASK 0x00000006
#define RING_REPORT_64K 0x00000002
#define RING_REPORT_128K 0x00000004
...
...
@@ -182,6 +180,9 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
#define CMD_3D (0x3<<29)
#define STATE3D_CONST_BLEND_COLOR_CMD (CMD_3D|(0x1d<<24)|(0x88<<16))
#define STATE3D_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16))
#define BR00_BITBLT_CLIENT 0x40000000
#define BR00_OP_COLOR_BLT 0x10000000
...
...
@@ -206,6 +207,8 @@ extern int i830_clear_bufs(struct inode *inode, struct file *filp,
#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
#define MI_BATCH_BUFFER ((0x30<<23)|1)
#define MI_BATCH_BUFFER_START (0x31<<23)
#define MI_BATCH_BUFFER_END (0xA<<23)
#define MI_BATCH_NON_SECURE (1)
...
...
drivers/char/drm/radeon.h
View file @
cd585d2f
...
...
@@ -48,10 +48,10 @@
#define DRIVER_NAME "radeon"
#define DRIVER_DESC "ATI Radeon"
#define DRIVER_DATE "20020
611
"
#define DRIVER_DATE "20020
828
"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR
5
#define DRIVER_MINOR
6
#define DRIVER_PATCHLEVEL 0
/* Interface history:
...
...
@@ -68,6 +68,11 @@
* 1.5 - Add r200 packets to cmdbuf ioctl
* - Add r200 function to init ioctl
* - Add 'scalar2' instruction to cmdbuf
* 1.6 - Add static agp memory manager
* Add irq handler (won't be turned on unless X server knows to)
* Add irq ioctls and irq_active getparam.
* Add wait command for cmdbuf ioctl
* Add agp offset query for getparam
*/
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
...
...
@@ -88,9 +93,18 @@
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)] = { radeon_mem_free, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)] = { radeon_mem_init_heap, 1, 1 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
/* Driver customization:
/* When a client dies:
* - Check for and clean up flipped page state
* - Free any alloced agp memory.
*
* DRM infrastructure takes care of reclaiming dma buffers.
*/
#define DRIVER_PRERELEASE() do { \
if ( dev->dev_private ) { \
...
...
@@ -98,17 +112,73 @@
if ( dev_priv->page_flipping ) { \
radeon_do_cleanup_pageflip( dev ); \
} \
radeon_mem_release( dev_priv->agp_heap ); \
} \
} while (0)
/* On unloading the module:
* - Free memory heap structure
* - Remove mappings made at startup and free dev_private.
*/
#define DRIVER_PRETAKEDOWN() do { \
if ( dev->dev_private ) radeon_do_cleanup_cp( dev ); \
if ( dev->dev_private ) { \
drm_radeon_private_t *dev_priv = dev->dev_private; \
radeon_mem_takedown( &(dev_priv->agp_heap) ); \
radeon_do_cleanup_cp( dev ); \
} \
} while (0)
/* DMA customization:
*/
#define __HAVE_DMA 1
#define __HAVE_DMA_IRQ 1
#define __HAVE_DMA_IRQ_BH 1
#define __HAVE_SHARED_IRQ 1
#define DRIVER_PREINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
u32 tmp; \
\
/* Clear bit if it's already high: */
\
tmp = RADEON_READ( RADEON_GEN_INT_STATUS ); \
tmp = tmp & RADEON_SW_INT_TEST_ACK; \
RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); \
\
/* Disable *all* interrupts */
\
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); \
} while (0)
#ifdef __linux__
#define IWH(x) init_waitqueue_head(x)
#else
#define IWH(x)
#endif
#define DRIVER_POSTINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
\
atomic_set(&dev_priv->irq_received, 0); \
atomic_set(&dev_priv->irq_emitted, 0); \
IWH(&dev_priv->irq_queue); \
\
/* Turn on SW_INT only */
\
RADEON_WRITE( RADEON_GEN_INT_CNTL, \
RADEON_SW_INT_ENABLE ); \
} while (0)
#define DRIVER_UNINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
if ( dev_priv ) { \
/* Disable *all* interrupts */
\
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); \
} \
} while (0)
/* Buffer customization:
*/
#define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t
...
...
drivers/char/drm/radeon_cp.c
View file @
cd585d2f
...
...
@@ -1412,6 +1412,9 @@ int radeon_cp_idle( DRM_IOCTL_ARGS )
LOCK_TEST_WITH_RETURN
(
dev
);
/* if (dev->irq) */
/* radeon_emit_and_wait_irq( dev ); */
return
radeon_do_cp_idle
(
dev_priv
);
}
...
...
drivers/char/drm/radeon_drm.h
View file @
cd585d2f
...
...
@@ -142,6 +142,9 @@
#define RADEON_CMD_PACKET3 5
/* emit hw packet */
#define RADEON_CMD_PACKET3_CLIP 6
/* emit hw packet wrapped in cliprects */
#define RADEON_CMD_SCALARS2 7
/* r200 stopgap */
#define RADEON_CMD_WAIT 8
/* emit hw wait commands -- note:
* doesn't make the cpu wait, just
* the graphics hardware */
typedef
union
{
...
...
@@ -161,8 +164,14 @@ typedef union {
struct
{
unsigned
char
cmd_type
,
buf_idx
,
pad0
,
pad1
;
}
dma
;
struct
{
unsigned
char
cmd_type
,
flags
,
pad0
,
pad1
;
}
wait
;
}
drm_radeon_cmd_header_t
;
#define RADEON_WAIT_2D 0x1
#define RADEON_WAIT_3D 0x2
#define RADEON_FRONT 0x1
#define RADEON_BACK 0x2
...
...
@@ -364,6 +373,11 @@ typedef struct {
#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t)
#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t)
#define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52)
#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR( 0x53, drm_radeon_mem_alloc_t)
#define DRM_IOCTL_RADEON_FREE DRM_IOW( 0x54, drm_radeon_mem_free_t)
#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t)
#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t)
#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t)
typedef
struct
drm_radeon_init
{
enum
{
...
...
@@ -499,14 +513,51 @@ typedef struct drm_radeon_indirect {
/* 1.3: An ioctl to get parameters that aren't available to the 3d
* client any other way.
*/
#define RADEON_PARAM_AGP_BUFFER_OFFSET 0x1
#define RADEON_PARAM_LAST_FRAME 0x2
#define RADEON_PARAM_LAST_DISPATCH 0x3
#define RADEON_PARAM_LAST_CLEAR 0x4
#define RADEON_PARAM_AGP_BUFFER_OFFSET 1
/* card offset of 1st agp buffer */
#define RADEON_PARAM_LAST_FRAME 2
#define RADEON_PARAM_LAST_DISPATCH 3
#define RADEON_PARAM_LAST_CLEAR 4
#define RADEON_PARAM_IRQ_ACTIVE 5
#define RADEON_PARAM_AGP_BASE 6
/* card offset of agp base */
typedef
struct
drm_radeon_getparam
{
int
param
;
int
*
value
;
}
drm_radeon_getparam_t
;
/* 1.6: Set up a memory manager for regions of shared memory:
*/
#define RADEON_MEM_REGION_AGP 1
#define RADEON_MEM_REGION_FB 2
typedef
struct
drm_radeon_mem_alloc
{
int
region
;
int
alignment
;
int
size
;
int
*
region_offset
;
/* offset from start of fb or agp */
}
drm_radeon_mem_alloc_t
;
typedef
struct
drm_radeon_mem_free
{
int
region
;
int
region_offset
;
}
drm_radeon_mem_free_t
;
typedef
struct
drm_radeon_mem_init_heap
{
int
region
;
int
size
;
int
start
;
}
drm_radeon_mem_init_heap_t
;
/* 1.6: Userspace can request & wait on irq's:
*/
typedef
struct
drm_radeon_irq_emit
{
int
*
irq_seq
;
}
drm_radeon_irq_emit_t
;
typedef
struct
drm_radeon_irq_wait
{
int
irq_seq
;
}
drm_radeon_irq_wait_t
;
#endif
drivers/char/drm/radeon_drv.h
View file @
cd585d2f
...
...
@@ -61,6 +61,15 @@ typedef struct drm_radeon_depth_clear_t {
u32
se_cntl
;
}
drm_radeon_depth_clear_t
;
struct
mem_block
{
struct
mem_block
*
next
;
struct
mem_block
*
prev
;
int
start
;
int
size
;
int
pid
;
/* 0: free, -1: heap, other: real pids */
};
typedef
struct
drm_radeon_private
{
drm_radeon_ring_buffer_t
ring
;
drm_radeon_sarea_t
*
sarea_priv
;
...
...
@@ -126,6 +135,14 @@ typedef struct drm_radeon_private {
drm_map_t
*
ring_rptr
;
drm_map_t
*
buffers
;
drm_map_t
*
agp_textures
;
struct
mem_block
*
agp_heap
;
struct
mem_block
*
fb_heap
;
wait_queue_head_t
irq_queue
;
atomic_t
irq_received
;
atomic_t
irq_emitted
;
}
drm_radeon_private_t
;
typedef
struct
drm_radeon_buf_priv
{
...
...
@@ -164,6 +181,20 @@ extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
extern
int
radeon_cp_getparam
(
DRM_IOCTL_ARGS
);
extern
int
radeon_cp_flip
(
DRM_IOCTL_ARGS
);
extern
int
radeon_mem_alloc
(
DRM_IOCTL_ARGS
);
extern
int
radeon_mem_free
(
DRM_IOCTL_ARGS
);
extern
int
radeon_mem_init_heap
(
DRM_IOCTL_ARGS
);
extern
void
radeon_mem_takedown
(
struct
mem_block
**
heap
);
extern
void
radeon_mem_release
(
struct
mem_block
*
heap
);
extern
int
radeon_irq_emit
(
DRM_IOCTL_ARGS
);
extern
int
radeon_irq_wait
(
DRM_IOCTL_ARGS
);
extern
int
radeon_emit_and_wait_irq
(
drm_device_t
*
dev
);
extern
int
radeon_wait_irq
(
drm_device_t
*
dev
,
int
irq_nr
);
extern
int
radeon_emit_irq
(
drm_device_t
*
dev
);
/* Flags for stats.boxes
*/
#define RADEON_BOX_DMA_IDLE 0x1
...
...
@@ -238,6 +269,16 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS );
? DRM_READ32( &dev_priv->scratch[(x)] ) \
: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
#define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
# define RADEON_SW_INT_ENABLE (1 << 25)
#define RADEON_GEN_INT_STATUS 0x0044
# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19)
# define RADEON_SW_INT_TEST_ACK (1 << 25)
# define RADEON_SW_INT_FIRE (1 << 26)
#define RADEON_HOST_PATH_CNTL 0x0130
# define RADEON_HDP_SOFT_RESET (1 << 26)
# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
...
...
@@ -526,6 +567,8 @@ extern int radeon_cp_flip( DRM_IOCTL_ARGS );
#define RADEON_TXFORMAT_ARGB4444 5
#define RADEON_TXFORMAT_ARGB8888 6
#define RADEON_TXFORMAT_RGBA8888 7
#define RADEON_TXFORMAT_VYUY422 10
#define RADEON_TXFORMAT_YVYU422 11
#define R200_PP_TXCBLEND_0 0x2f00
#define R200_PP_TXCBLEND_1 0x2f10
...
...
drivers/char/drm/radeon_irq.c
0 → 100644
View file @
cd585d2f
/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*-
*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
* The Weather Channel (TM) funded Tungsten Graphics to develop the
* initial release of the Radeon 8500 driver under the XFree86 license.
* This notice must be preserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* 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
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "radeon.h"
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
/* Interrupts - Used for device synchronization and flushing in the
* following circumstances:
*
* - Exclusive FB access with hw idle:
* - Wait for GUI Idle (?) interrupt, then do normal flush.
*
* - Frame throttling, NV_fence:
* - Drop marker irq's into command stream ahead of time.
* - Wait on irq's with lock *not held*
* - Check each for termination condition
*
* - Internally in cp_getbuffer, etc:
* - as above, but wait with lock held???
*
* NOTE: These functions are misleadingly named -- the irq's aren't
* tied to dma at all, this is just a hangover from dri prehistory.
*/
void
DRM
(
dma_service
)(
DRM_IRQ_ARGS
)
{
drm_device_t
*
dev
=
(
drm_device_t
*
)
arg
;
drm_radeon_private_t
*
dev_priv
=
(
drm_radeon_private_t
*
)
dev
->
dev_private
;
u32
temp
;
/* Need to wait for fifo to drain?
*/
temp
=
RADEON_READ
(
RADEON_GEN_INT_STATUS
);
temp
=
temp
&
RADEON_SW_INT_TEST_ACK
;
if
(
temp
==
0
)
return
;
RADEON_WRITE
(
RADEON_GEN_INT_STATUS
,
temp
);
atomic_inc
(
&
dev_priv
->
irq_received
);
#ifdef __linux__
queue_task
(
&
dev
->
tq
,
&
tq_immediate
);
mark_bh
(
IMMEDIATE_BH
);
#endif
/* __linux__ */
#ifdef __FreeBSD__
taskqueue_enqueue
(
taskqueue_swi
,
&
dev
->
task
);
#endif
/* __FreeBSD__ */
}
void
DRM
(
dma_immediate_bh
)(
DRM_TASKQUEUE_ARGS
)
{
drm_device_t
*
dev
=
(
drm_device_t
*
)
arg
;
drm_radeon_private_t
*
dev_priv
=
(
drm_radeon_private_t
*
)
dev
->
dev_private
;
#ifdef __linux__
wake_up_interruptible
(
&
dev_priv
->
irq_queue
);
#endif
/* __linux__ */
#ifdef __FreeBSD__
wakeup
(
&
dev_priv
->
irq_queue
);
#endif
}
int
radeon_emit_irq
(
drm_device_t
*
dev
)
{
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
RING_LOCALS
;
atomic_inc
(
&
dev_priv
->
irq_emitted
);
BEGIN_RING
(
2
);
OUT_RING
(
CP_PACKET0
(
RADEON_GEN_INT_STATUS
,
0
)
);
OUT_RING
(
RADEON_SW_INT_FIRE
);
ADVANCE_RING
();
COMMIT_RING
();
return
atomic_read
(
&
dev_priv
->
irq_emitted
);
}
int
radeon_wait_irq
(
drm_device_t
*
dev
,
int
irq_nr
)
{
drm_radeon_private_t
*
dev_priv
=
(
drm_radeon_private_t
*
)
dev
->
dev_private
;
#ifdef __linux__
DECLARE_WAITQUEUE
(
entry
,
current
);
unsigned
long
end
=
jiffies
+
HZ
*
3
;
#endif
/* __linux__ */
int
ret
=
0
;
if
(
atomic_read
(
&
dev_priv
->
irq_received
)
>=
irq_nr
)
return
0
;
dev_priv
->
stats
.
boxes
|=
RADEON_BOX_WAIT_IDLE
;
#ifdef __linux__
add_wait_queue
(
&
dev_priv
->
irq_queue
,
&
entry
);
for
(;;)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
if
(
atomic_read
(
&
dev_priv
->
irq_received
)
>=
irq_nr
)
break
;
if
((
signed
)(
end
-
jiffies
)
<=
0
)
{
ret
=
-
EBUSY
;
/* Lockup? Missed irq? */
break
;
}
schedule_timeout
(
HZ
*
3
);
if
(
signal_pending
(
current
))
{
ret
=
-
EINTR
;
break
;
}
}
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
&
dev_priv
->
irq_queue
,
&
entry
);
return
ret
;
#endif
/* __linux__ */
#ifdef __FreeBSD__
ret
=
tsleep
(
&
dev_priv
->
irq_queue
,
PZERO
|
PCATCH
,
\
"rdnirq"
,
3
*
hz
);
if
(
(
ret
==
EWOULDBLOCK
)
||
(
ret
==
EINTR
)
)
return
DRM_ERR
(
EBUSY
);
return
ret
;
#endif
/* __FreeBSD__ */
}
int
radeon_emit_and_wait_irq
(
drm_device_t
*
dev
)
{
return
radeon_wait_irq
(
dev
,
radeon_emit_irq
(
dev
)
);
}
/* Needs the lock as it touches the ring.
*/
int
radeon_irq_emit
(
DRM_IOCTL_ARGS
)
{
DRM_DEVICE
;
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_radeon_irq_emit_t
emit
;
int
result
;
LOCK_TEST_WITH_RETURN
(
dev
);
if
(
!
dev_priv
)
{
DRM_ERROR
(
"%s called with no initialization
\n
"
,
__FUNCTION__
);
return
DRM_ERR
(
EINVAL
);
}
DRM_COPY_FROM_USER_IOCTL
(
emit
,
(
drm_radeon_irq_emit_t
*
)
data
,
sizeof
(
emit
)
);
result
=
radeon_emit_irq
(
dev
);
if
(
DRM_COPY_TO_USER
(
emit
.
irq_seq
,
&
result
,
sizeof
(
int
)
)
)
{
DRM_ERROR
(
"copy_to_user
\n
"
);
return
DRM_ERR
(
EFAULT
);
}
return
0
;
}
/* Doesn't need the hardware lock.
*/
int
radeon_irq_wait
(
DRM_IOCTL_ARGS
)
{
DRM_DEVICE
;
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_radeon_irq_wait_t
irqwait
;
if
(
!
dev_priv
)
{
DRM_ERROR
(
"%s called with no initialization
\n
"
,
__FUNCTION__
);
return
DRM_ERR
(
EINVAL
);
}
DRM_COPY_FROM_USER_IOCTL
(
irqwait
,
(
drm_radeon_irq_wait_t
*
)
data
,
sizeof
(
irqwait
)
);
return
radeon_wait_irq
(
dev
,
irqwait
.
irq_seq
);
}
drivers/char/drm/radeon_mem.c
0 → 100644
View file @
cd585d2f
/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*-
*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
* The Weather Channel (TM) funded Tungsten Graphics to develop the
* initial release of the Radeon 8500 driver under the XFree86 license.
* This notice must be preserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* 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
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "radeon.h"
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
/* Very simple allocator for agp memory, working on a static range
* already mapped into each client's address space.
*/
static
struct
mem_block
*
split_block
(
struct
mem_block
*
p
,
int
start
,
int
size
,
int
pid
)
{
/* Maybe cut off the start of an existing block */
if
(
start
>
p
->
start
)
{
struct
mem_block
*
newblock
=
DRM_MALLOC
(
sizeof
(
*
newblock
));
if
(
!
newblock
)
goto
out
;
newblock
->
start
=
start
;
newblock
->
size
=
p
->
size
-
(
start
-
p
->
start
);
newblock
->
pid
=
0
;
newblock
->
next
=
p
->
next
;
newblock
->
prev
=
p
;
p
->
next
->
prev
=
newblock
;
p
->
next
=
newblock
;
p
->
size
-=
newblock
->
size
;
p
=
newblock
;
}
/* Maybe cut off the end of an existing block */
if
(
size
<
p
->
size
)
{
struct
mem_block
*
newblock
=
DRM_MALLOC
(
sizeof
(
*
newblock
));
if
(
!
newblock
)
goto
out
;
newblock
->
start
=
start
+
size
;
newblock
->
size
=
p
->
size
-
size
;
newblock
->
pid
=
0
;
newblock
->
next
=
p
->
next
;
newblock
->
prev
=
p
;
p
->
next
->
prev
=
newblock
;
p
->
next
=
newblock
;
p
->
size
=
size
;
}
out:
/* Our block is in the middle */
p
->
pid
=
pid
;
return
p
;
}
static
struct
mem_block
*
alloc_block
(
struct
mem_block
*
heap
,
int
size
,
int
align2
,
int
pid
)
{
struct
mem_block
*
p
;
int
mask
=
(
1
<<
align2
)
-
1
;
for
(
p
=
heap
->
next
;
p
!=
heap
;
p
=
p
->
next
)
{
int
start
=
(
p
->
start
+
mask
)
&
~
mask
;
if
(
p
->
pid
==
0
&&
start
+
size
<=
p
->
start
+
p
->
size
)
return
split_block
(
p
,
start
,
size
,
pid
);
}
return
NULL
;
}
static
struct
mem_block
*
find_block
(
struct
mem_block
*
heap
,
int
start
)
{
struct
mem_block
*
p
;
for
(
p
=
heap
->
next
;
p
!=
heap
;
p
=
p
->
next
)
if
(
p
->
start
==
start
)
return
p
;
return
NULL
;
}
static
void
free_block
(
struct
mem_block
*
p
)
{
p
->
pid
=
0
;
/* Assumes a single contiguous range. Needs a special pid in
* 'heap' to stop it being subsumed.
*/
if
(
p
->
next
->
pid
==
0
)
{
struct
mem_block
*
q
=
p
->
next
;
p
->
size
+=
q
->
size
;
p
->
next
=
q
->
next
;
p
->
next
->
prev
=
p
;
DRM_FREE
(
p
);
}
if
(
p
->
prev
->
pid
==
0
)
{
struct
mem_block
*
q
=
p
->
prev
;
q
->
size
+=
p
->
size
;
q
->
next
=
p
->
next
;
q
->
next
->
prev
=
q
;
DRM_FREE
(
p
);
}
}
static
void
print_heap
(
struct
mem_block
*
heap
)
{
struct
mem_block
*
p
;
for
(
p
=
heap
->
next
;
p
!=
heap
;
p
=
p
->
next
)
DRM_DEBUG
(
"0x%x..0x%x (0x%x) -- owner %d
\n
"
,
p
->
start
,
p
->
start
+
p
->
size
,
p
->
size
,
p
->
pid
);
}
/* Initialize. How to check for an uninitialized heap?
*/
static
int
init_heap
(
struct
mem_block
**
heap
,
int
start
,
int
size
)
{
struct
mem_block
*
blocks
=
DRM_MALLOC
(
sizeof
(
*
blocks
));
if
(
!
blocks
)
return
-
ENOMEM
;
*
heap
=
DRM_MALLOC
(
sizeof
(
**
heap
));
if
(
!*
heap
)
{
DRM_FREE
(
blocks
);
return
-
ENOMEM
;
}
blocks
->
start
=
start
;
blocks
->
size
=
size
;
blocks
->
pid
=
0
;
blocks
->
next
=
blocks
->
prev
=
*
heap
;
memset
(
*
heap
,
0
,
sizeof
(
**
heap
)
);
(
*
heap
)
->
pid
=
-
1
;
(
*
heap
)
->
next
=
(
*
heap
)
->
prev
=
blocks
;
return
0
;
}
/* Free all blocks associated with the releasing pid.
*/
void
radeon_mem_release
(
struct
mem_block
*
heap
)
{
int
pid
=
DRM_CURRENTPID
;
struct
mem_block
*
p
;
if
(
!
heap
||
!
heap
->
next
)
return
;
for
(
p
=
heap
->
next
;
p
!=
heap
;
p
=
p
->
next
)
{
if
(
p
->
pid
==
pid
)
p
->
pid
=
0
;
}
/* Assumes a single contiguous range. Needs a special pid in
* 'heap' to stop it being subsumed.
*/
for
(
p
=
heap
->
next
;
p
!=
heap
;
p
=
p
->
next
)
{
while
(
p
->
pid
==
0
&&
p
->
next
->
pid
==
0
)
{
struct
mem_block
*
q
=
p
->
next
;
p
->
size
+=
q
->
size
;
p
->
next
=
q
->
next
;
p
->
next
->
prev
=
p
;
DRM_FREE
(
q
);
}
}
}
/* Shutdown.
*/
void
radeon_mem_takedown
(
struct
mem_block
**
heap
)
{
struct
mem_block
*
p
;
if
(
!*
heap
)
return
;
for
(
p
=
(
*
heap
)
->
next
;
p
!=
*
heap
;
)
{
struct
mem_block
*
q
=
p
;
p
=
p
->
next
;
DRM_FREE
(
q
);
}
DRM_FREE
(
*
heap
);
*
heap
=
0
;
}
/* IOCTL HANDLERS */
static
struct
mem_block
**
get_heap
(
drm_radeon_private_t
*
dev_priv
,
int
region
)
{
switch
(
region
)
{
case
RADEON_MEM_REGION_AGP
:
return
&
dev_priv
->
agp_heap
;
case
RADEON_MEM_REGION_FB
:
return
&
dev_priv
->
fb_heap
;
default:
return
0
;
}
}
int
radeon_mem_alloc
(
DRM_IOCTL_ARGS
)
{
DRM_DEVICE
;
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_radeon_mem_alloc_t
alloc
;
struct
mem_block
*
block
,
**
heap
;
if
(
!
dev_priv
)
{
DRM_ERROR
(
"%s called with no initialization
\n
"
,
__FUNCTION__
);
return
DRM_ERR
(
EINVAL
);
}
DRM_COPY_FROM_USER_IOCTL
(
alloc
,
(
drm_radeon_mem_alloc_t
*
)
data
,
sizeof
(
alloc
)
);
heap
=
get_heap
(
dev_priv
,
alloc
.
region
);
if
(
!
heap
||
!*
heap
)
return
DRM_ERR
(
EFAULT
);
/* Make things easier on ourselves: all allocations at least
* 4k aligned.
*/
if
(
alloc
.
alignment
<
12
)
alloc
.
alignment
=
12
;
block
=
alloc_block
(
*
heap
,
alloc
.
size
,
alloc
.
alignment
,
DRM_CURRENTPID
);
if
(
!
block
)
return
DRM_ERR
(
ENOMEM
);
if
(
DRM_COPY_TO_USER
(
alloc
.
region_offset
,
&
block
->
start
,
sizeof
(
int
)
)
)
{
DRM_ERROR
(
"copy_to_user
\n
"
);
return
DRM_ERR
(
EFAULT
);
}
return
0
;
}
int
radeon_mem_free
(
DRM_IOCTL_ARGS
)
{
DRM_DEVICE
;
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_radeon_mem_free_t
memfree
;
struct
mem_block
*
block
,
**
heap
;
if
(
!
dev_priv
)
{
DRM_ERROR
(
"%s called with no initialization
\n
"
,
__FUNCTION__
);
return
DRM_ERR
(
EINVAL
);
}
DRM_COPY_FROM_USER_IOCTL
(
memfree
,
(
drm_radeon_mem_free_t
*
)
data
,
sizeof
(
memfree
)
);
heap
=
get_heap
(
dev_priv
,
memfree
.
region
);
if
(
!
heap
||
!*
heap
)
return
DRM_ERR
(
EFAULT
);
block
=
find_block
(
*
heap
,
memfree
.
region_offset
);
if
(
!
block
)
return
DRM_ERR
(
EFAULT
);
if
(
block
->
pid
!=
DRM_CURRENTPID
)
return
DRM_ERR
(
EPERM
);
free_block
(
block
);
return
0
;
}
int
radeon_mem_init_heap
(
DRM_IOCTL_ARGS
)
{
DRM_DEVICE
;
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_radeon_mem_init_heap_t
initheap
;
struct
mem_block
**
heap
;
if
(
!
dev_priv
)
{
DRM_ERROR
(
"%s called with no initialization
\n
"
,
__FUNCTION__
);
return
DRM_ERR
(
EINVAL
);
}
DRM_COPY_FROM_USER_IOCTL
(
initheap
,
(
drm_radeon_mem_init_heap_t
*
)
data
,
sizeof
(
initheap
)
);
heap
=
get_heap
(
dev_priv
,
initheap
.
region
);
if
(
!
heap
)
return
DRM_ERR
(
EFAULT
);
if
(
*
heap
)
{
DRM_ERROR
(
"heap already initialized?"
);
return
DRM_ERR
(
EFAULT
);
}
return
init_heap
(
heap
,
initheap
.
start
,
initheap
.
size
);
}
drivers/char/drm/radeon_state.c
View file @
cd585d2f
...
...
@@ -719,7 +719,6 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
RING_LOCALS
;
DRM_DEBUG
(
"
\n
"
);
/* Do some trivial performance monitoring...
*/
if
(
dev_priv
->
do_boxes
)
...
...
@@ -1088,6 +1087,8 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
case
RADEON_TXFORMAT_ARGB1555
:
case
RADEON_TXFORMAT_RGB565
:
case
RADEON_TXFORMAT_ARGB4444
:
case
RADEON_TXFORMAT_VYUY422
:
case
RADEON_TXFORMAT_YVYU422
:
format
=
RADEON_COLOR_FORMAT_RGB565
;
tex_width
=
tex
->
width
*
2
;
blit_width
=
image
->
width
*
2
;
...
...
@@ -1226,6 +1227,7 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
return
ret
;
}
static
void
radeon_cp_dispatch_stipple
(
drm_device_t
*
dev
,
u32
*
stipple
)
{
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
...
...
@@ -1306,6 +1308,9 @@ static int radeon_do_init_pageflip( drm_device_t *dev )
return
0
;
}
/* Called whenever a client dies, from DRM(release).
* NOTE: Lock isn't necessarily held when this is called!
*/
int
radeon_do_cleanup_pageflip
(
drm_device_t
*
dev
)
{
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
...
...
@@ -1936,14 +1941,18 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
if
(
i
<
cmdbuf
->
nbox
)
{
if
(
DRM_COPY_FROM_USER_UNCHECKED
(
&
box
,
&
boxes
[
i
],
sizeof
(
box
)
))
return
DRM_ERR
(
EFAULT
);
/* FIXME The second and subsequent times round this loop, send a
* WAIT_UNTIL_3D_IDLE before calling emit_clip_rect(). This
* fixes a lockup on fast machines when sending several
* cliprects with a cmdbuf, as when waving a 2D window over
* a 3D window. Something in the commands from user space
* seems to hang the card when they're sent several times
* in a row. That would be the correct place to fix it but
* this works around it until I can figure that out - Tim Smith */
/* FIXME The second and subsequent times round
* this loop, send a WAIT_UNTIL_3D_IDLE before
* calling emit_clip_rect(). This fixes a
* lockup on fast machines when sending
* several cliprects with a cmdbuf, as when
* waving a 2D window over a 3D
* window. Something in the commands from user
* space seems to hang the card when they're
* sent several times in a row. That would be
* the correct place to fix it but this works
* around it until I can figure that out - Tim
* Smith */
if
(
i
)
{
BEGIN_RING
(
2
);
RADEON_WAIT_UNTIL_3D_IDLE
();
...
...
@@ -1967,6 +1976,34 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
}
static
int
radeon_emit_wait
(
drm_device_t
*
dev
,
int
flags
)
{
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
RING_LOCALS
;
DRM_DEBUG
(
"%s: %x
\n
"
,
__FUNCTION__
,
flags
);
switch
(
flags
)
{
case
RADEON_WAIT_2D
:
BEGIN_RING
(
2
);
RADEON_WAIT_UNTIL_2D_IDLE
();
ADVANCE_RING
();
break
;
case
RADEON_WAIT_3D
:
BEGIN_RING
(
2
);
RADEON_WAIT_UNTIL_3D_IDLE
();
ADVANCE_RING
();
break
;
case
RADEON_WAIT_2D
|
RADEON_WAIT_3D
:
BEGIN_RING
(
2
);
RADEON_WAIT_UNTIL_IDLE
();
ADVANCE_RING
();
break
;
default:
return
DRM_ERR
(
EINVAL
);
}
return
0
;
}
int
radeon_cp_cmdbuf
(
DRM_IOCTL_ARGS
)
{
...
...
@@ -1989,7 +2026,6 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_COPY_FROM_USER_IOCTL
(
cmdbuf
,
(
drm_radeon_cmd_buffer_t
*
)
data
,
sizeof
(
cmdbuf
)
);
DRM_DEBUG
(
"pid=%d
\n
"
,
DRM_CURRENTPID
);
RING_SPACE_TEST_WITH_RETURN
(
dev_priv
);
VB_AGE_TEST_WITH_RETURN
(
dev_priv
);
...
...
@@ -2080,6 +2116,14 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
return
DRM_ERR
(
EINVAL
);
}
break
;
case
RADEON_CMD_WAIT
:
DRM_DEBUG
(
"RADEON_CMD_WAIT
\n
"
);
if
(
radeon_emit_wait
(
dev
,
header
.
wait
.
flags
))
{
DRM_ERROR
(
"radeon_emit_wait failed
\n
"
);
return
DRM_ERR
(
EINVAL
);
}
break
;
default:
DRM_ERROR
(
"bad cmd_type %d at %p
\n
"
,
header
.
header
.
cmd_type
,
...
...
@@ -2128,6 +2172,12 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
dev_priv
->
stats
.
last_clear_reads
++
;
value
=
GET_SCRATCH
(
2
);
break
;
case
RADEON_PARAM_IRQ_ACTIVE
:
value
=
dev
->
irq
?
1
:
0
;
break
;
case
RADEON_PARAM_AGP_BASE
:
value
=
dev_priv
->
agp_vm_start
;
break
;
default:
return
DRM_ERR
(
EINVAL
);
}
...
...
drivers/ide/ide.c
View file @
cd585d2f
...
...
@@ -980,7 +980,7 @@ static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
best
=
NULL
;
drive
=
hwgroup
->
drive
;
do
{
if
(
!
list_empty
(
&
drive
->
queue
.
queue_head
)
&&
(
!
drive
->
sleep
||
time_after_eq
(
jiffies
,
drive
->
sleep
)))
{
if
(
!
blk_queue_empty
(
&
drive
->
queue
)
&&
(
!
drive
->
sleep
||
time_after_eq
(
jiffies
,
drive
->
sleep
)))
{
if
(
!
best
||
(
drive
->
sleep
&&
(
!
best
->
sleep
||
0
<
(
signed
long
)(
best
->
sleep
-
drive
->
sleep
)))
||
(
!
best
->
sleep
&&
0
<
(
signed
long
)(
WAKEUP
(
best
)
-
WAKEUP
(
drive
))))
...
...
include/asm-alpha/ide.h
View file @
cd585d2f
...
...
@@ -80,17 +80,6 @@ static __inline__ void ide_init_default_hwifs(void)
#endif
}
#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
#define ide_check_region(from,extent) check_region((from), (extent))
#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
#define ide_release_region(from,extent) release_region((from), (extent))
#define ide_ack_intr(hwif) (1)
#define ide_fix_driveid(id) do {} while (0)
#define ide_release_lock(lock) do {} while (0)
#define ide_get_lock(lock, hdlr, data) do {} while (0)
#endif
/* __KERNEL__ */
#endif
/* __ASMalpha_IDE_H */
include/asm-alpha/rwsem.h
View file @
cd585d2f
...
...
@@ -93,14 +93,16 @@ static inline void __down_read(struct rw_semaphore *sem)
*/
static
inline
int
__down_read_trylock
(
struct
rw_semaphore
*
sem
)
{
long
res
,
tmp
;
long
old
,
new
,
res
;
res
=
sem
->
count
;
do
{
tmp
=
res
+
RWSEM_ACTIVE_READ_BIAS
;
if
(
tmp
<=
0
)
new
=
res
+
RWSEM_ACTIVE_READ_BIAS
;
if
(
new
<=
0
)
break
;
}
while
(
cmpxchg
(
&
sem
->
count
,
res
,
tmp
)
!=
res
);
old
=
res
;
res
=
cmpxchg
(
&
sem
->
count
,
old
,
new
);
}
while
(
res
!=
old
);
return
res
>=
0
?
1
:
0
;
}
...
...
include/asm-alpha/unistd.h
View file @
cd585d2f
...
...
@@ -331,6 +331,18 @@
#define __NR_removexattr 391
#define __NR_lremovexattr 392
#define __NR_fremovexattr 393
#define __NR_futex 394
#define __NR_sched_setaffinity 395
#define __NR_sched_getaffinity 396
#define __NR_tuxcall 397
#define __NR_io_setup 398
#define __NR_io_destroy 399
#define __NR_io_getevents 400
#define __NR_io_submit 401
#define __NR_io_cancel 402
#define __NR_alloc_hugepages 403
#define __NR_free_hugepages 404
#define __NR_exit_group 405
#if defined(__GNUC__)
...
...
kernel/exit.c
View file @
cd585d2f
...
...
@@ -131,9 +131,14 @@ int session_of_pgrp(int pgrp)
for_each_task_pid
(
pgrp
,
PIDTYPE_PGID
,
p
,
l
,
pid
)
if
(
p
->
session
>
0
)
{
sid
=
p
->
session
;
break
;
goto
out
;
}
p
=
find_task_by_pid
(
pgrp
);
if
(
p
)
sid
=
p
->
session
;
out:
read_unlock
(
&
tasklist_lock
);
return
sid
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment