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
Kirill Smelkov
linux
Commits
76f92de7
Commit
76f92de7
authored
Sep 23, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge with DRI CVS tree
parent
60abdcb3
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
952 additions
and
354 deletions
+952
-354
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
No files found.
drivers/char/drm/Makefile
View file @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -26,8 +26,8 @@
*
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
* Jeff Hartmann <jhartmann@valinux.com>
*
Keith Whitwell <keithw@valinux
.com>
*
Abraham vd Merwe <abraham@2d3d.co.za>
*
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,36 +200,24 @@ 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
;
buf_priv
->
virtual
=
(
void
*
)
do_mmap
(
filp
,
0
,
buf
->
total
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
buf
->
bus_address
);
dev_priv
->
mmap_buffer
=
NULL
;
filp
->
f_op
=
old_fops
;
if
((
unsigned
long
)
buf_priv
->
virtual
>
-
1024UL
)
{
/* Real error */
DRM_DEBUG
(
"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
;
down_write
(
&
current
->
mm
->
mmap_sem
);
old_fops
=
filp
->
f_op
;
filp
->
f_op
=
&
i830_buffer_fops
;
dev_priv
->
mmap_buffer
=
buf
;
buf_priv
->
virtual
=
(
void
*
)
do_mmap
(
filp
,
0
,
buf
->
total
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
buf
->
bus_address
);
dev_priv
->
mmap_buffer
=
NULL
;
filp
->
f_op
=
old_fops
;
if
((
unsigned
long
)
buf_priv
->
virtual
>
-
1024UL
)
{
/* Real error */
DRM_ERROR
(
"mmap error
\n
"
);
retcode
=
(
signed
int
)
buf_priv
->
virtual
;
buf_priv
->
virtual
=
0
;
}
up_write
(
&
current
->
mm
->
mmap_sem
);
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
if
(
buf_priv
->
currently_mapped
!=
I830_BUF_MAPPED
)
return
-
EINVAL
;
retcode
=
do_munmap
(
current
->
mm
,
(
unsigned
long
)
buf_priv
->
virtual
,
(
size_t
)
buf
->
total
);
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,38 +539,57 @@ 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
)
static
void
i830EmitContextVerified
(
drm_device_t
*
dev
,
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
++
)
{
BEGIN_LP_RING
(
I830_CTX_SETUP_SIZE
+
2
);
OUT_RING
(
GFX_OP_STIPPLE
);
OUT_RING
(
0
);
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
{
DRM_ERROR
(
"Skipping %d
\n
"
,
i
);
}
}
OUT_RING
(
STATE3D_CONST_BLEND_COLOR_CMD
);
OUT_RING
(
code
[
I830_CTXREG_BLENDCOLR
]
);
j
+=
2
;
#if 0
if ((tmp & (7<<29)) == (3<<29) &&
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
++
;
}
else
{
printk
("Skipping %d\n", i);
DRM_ERROR
(
"Skipping %d
\n
"
,
i
);
}
#else
OUT_RING
(
tmp
);
j
++
;
#endif
}
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
|
sarea_priv
->
vertex_prim
|
((
used
/
4
)
-
2
));
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,80 +1027,35 @@ 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
);
OUT_RING
(
CMD_STORE_DWORD_IDX
);
OUT_RING
(
20
);
OUT_RING
(
dev_priv
->
counter
);
OUT_RING
(
0
);
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
(
CMD_STORE_DWORD_IDX
);
OUT_RING
(
buf_priv
->
my_use_idx
);
OUT_RING
(
I830_BUF_FREE
);
OUT_RING
(
CMD_REPORT_HEAD
);
OUT_RING
(
0
);
ADVANCE_LP_RING
();
}
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
)
{
drm_i830_private_t
*
dev_priv
=
dev
->
dev_private
;
RING_LOCALS
;
i830_kernel_lost_context
(
dev
);
BEGIN_LP_RING
(
2
);
OUT_RING
(
CMD_REPORT_HEAD
);
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
);
}
static
inline
void
i830_dma_quiescent_emit
(
drm_device_t
*
dev
)
void
i830_dma_quiescent
(
drm_device_t
*
dev
)
{
drm_i830_private_t
*
dev_priv
=
dev
->
dev_private
;
RING_LOCALS
;
...
...
@@ -1119,79 +1066,27 @@ static inline void i830_dma_quiescent_emit(drm_device_t *dev)
OUT_RING
(
INST_PARSER_CLIENT
|
INST_OP_FLUSH
|
INST_FLUSH_MAP_CACHE
);
OUT_RING
(
CMD_REPORT_HEAD
);
OUT_RING
(
0
);
OUT_RING
(
GFX_OP_USER_INTERRUPT
);
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
);
}
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_i830_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_device_dma_t
*
dma
=
dev
->
dma
;
unsigned
long
end
;
int
i
,
ret
=
0
;
int
i
,
ret
=
0
;
RING_LOCALS
;
i830_kernel_lost_context
(
dev
);
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
);
BEGIN_LP_RING
(
2
);
OUT_RING
(
CMD_REPORT_HEAD
);
OUT_RING
(
0
);
ADVANCE_LP_RING
();
i830_wait_ring
(
dev
,
dev_priv
->
ring
.
Size
-
8
);
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
;
...
...
@@ -1242,8 +1137,7 @@ 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
,
unsigned
long
arg
)
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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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,22 +112,78 @@
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
#define DRIVER_AGP_BUFFERS_MAP( dev )
\
#define DRIVER_AGP_BUFFERS_MAP( dev ) \
((drm_radeon_private_t *)((dev)->dev_private))->buffers
#endif
drivers/char/drm/radeon_cp.c
View file @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
...
...
@@ -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 @
76f92de7
/* 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 @
76f92de7
/* 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 @
76f92de7
...
...
@@ -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
);
}
...
...
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