Import DRM drivers, brought into shape by Yorick Hardy, posted to tech-x11.
Minor modifications by me: -use an mi device major number -(coarsly) divided into pci card specific and less specific parts, moved the latter to dev/drm -renamed autoconf attributes to reflect this Todo: -adapt all card frontends but i915 to drm include file location -review the mtrr change -make the change to agp_i810.c coexist with the fix for buggy VESA BIOSes which is commented out temporarily -RCS IDs etc style stuff -LKM support (rescan support for vga) -test
This commit is contained in:
parent
f8ef9d1431
commit
2d9e04fc35
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mtrr_i686.c,v 1.8 2006/11/16 01:32:39 christos Exp $ */
|
||||
/* $NetBSD: mtrr_i686.c,v 1.9 2007/03/20 18:05:25 drochner Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mtrr_i686.c,v 1.8 2006/11/16 01:32:39 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mtrr_i686.c,v 1.9 2007/03/20 18:05:25 drochner Exp $");
|
||||
|
||||
#include "opt_multiprocessor.h"
|
||||
|
||||
|
@ -598,7 +598,8 @@ i686_mtrr_setone(struct mtrr *mtrrp, struct proc *p)
|
|||
curhigh = curlow + mtrr_var[i].len;
|
||||
if (low == curlow && high == curhigh &&
|
||||
(!(mtrr_var[i].flags & MTRR_PRIVATE) ||
|
||||
mtrr_var[i].owner == p->p_pid)) {
|
||||
((mtrrp->flags & MTRR_PRIVATE) && (p != NULL) &&
|
||||
(mtrr_var[i].owner == p->p_pid)))) {
|
||||
freep = &mtrr_var[i];
|
||||
break;
|
||||
}
|
||||
|
@ -606,7 +607,8 @@ i686_mtrr_setone(struct mtrr *mtrrp, struct proc *p)
|
|||
(low >= curlow && low < curhigh)) &&
|
||||
((mtrr_var[i].type != mtrrp->type) ||
|
||||
((mtrr_var[i].flags & MTRR_PRIVATE) &&
|
||||
mtrr_var[i].owner != p->p_pid))) {
|
||||
(!(mtrrp->flags & MTRR_PRIVATE) || (p == NULL) ||
|
||||
(mtrr_var[i].owner != p->p_pid))))) {
|
||||
return EBUSY;
|
||||
}
|
||||
}
|
||||
|
@ -614,7 +616,7 @@ i686_mtrr_setone(struct mtrr *mtrrp, struct proc *p)
|
|||
return EBUSY;
|
||||
mtrrp->flags &= ~MTRR_CANTSET;
|
||||
*freep = *mtrrp;
|
||||
freep->owner = mtrrp->flags & MTRR_PRIVATE ? p->p_pid : 0;
|
||||
freep->owner = (mtrrp->flags & MTRR_PRIVATE) ? p->p_pid : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files,v 1.835 2007/03/17 06:41:36 dyoung Exp $
|
||||
# $NetBSD: files,v 1.836 2007/03/20 18:05:25 drochner Exp $
|
||||
|
||||
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
|
||||
|
||||
|
@ -963,6 +963,10 @@ file dev/ic/acpipmtimer.c acpipmtimer
|
|||
device hpet
|
||||
file dev/ic/hpet.c hpet needs-flag
|
||||
|
||||
# DRM - Direct Rendering Infrastructure: dev/drm
|
||||
define drm {}
|
||||
include dev/drm/files.drm
|
||||
|
||||
# Definitions for wscons
|
||||
# device attributes: display, display with emulator, keyboard, and mouse
|
||||
#
|
||||
|
@ -990,7 +994,7 @@ defparam opt_vga.h VGA_CONSOLE_SCREENTYPE
|
|||
defflag opt_vga.h VGA_CONSOLE_ATI_BROKEN_FONTSEL
|
||||
defflag opt_vga.h VGA_RASTERCONSOLE
|
||||
defflag opt_vga.h VGA_RESET
|
||||
device vga: wsemuldisplaydev, pcdisplayops
|
||||
device vga: wsemuldisplaydev, pcdisplayops, drm
|
||||
file dev/ic/vga.c vga & !vga_rasterconsole needs-flag
|
||||
file dev/ic/vga_raster.c vga_rasterconsole needs-flag
|
||||
file dev/ic/vga_subr.c vga | vga_rasterconsole
|
||||
|
|
|
@ -0,0 +1,713 @@
|
|||
/**
|
||||
* \file drm.h
|
||||
* Header for the Direct Rendering Manager
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
* \par Acknowledgments:
|
||||
* Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm.h,v 1.12 2006/05/17 06:36:28 anholt Exp $");
|
||||
*/
|
||||
|
||||
/**
|
||||
* \mainpage
|
||||
*
|
||||
* The Direct Rendering Manager (DRM) is a device-independent kernel-level
|
||||
* device driver that provides support for the XFree86 Direct Rendering
|
||||
* Infrastructure (DRI).
|
||||
*
|
||||
* The DRM supports the Direct Rendering Infrastructure (DRI) in four major
|
||||
* ways:
|
||||
* -# The DRM provides synchronized access to the graphics hardware via
|
||||
* the use of an optimized two-tiered lock.
|
||||
* -# The DRM enforces the DRI security policy for access to the graphics
|
||||
* hardware by only allowing authenticated X11 clients access to
|
||||
* restricted regions of memory.
|
||||
* -# The DRM provides a generic DMA engine, complete with multiple
|
||||
* queues and the ability to detect the need for an OpenGL context
|
||||
* switch.
|
||||
* -# The DRM is extensible via the use of small device-specific modules
|
||||
* that rely extensively on the API exported by the DRM module.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DRM_H_
|
||||
#define _DRM_H_
|
||||
|
||||
#ifndef __user
|
||||
#define __user
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define DEPRECATED __attribute__ ((deprecated))
|
||||
#else
|
||||
# define DEPRECATED
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(__KERNEL__)
|
||||
#include <linux/config.h>
|
||||
#endif
|
||||
#include <asm/ioctl.h> /* For _IO* macros */
|
||||
#define DRM_IOCTL_NR(n) _IOC_NR(n)
|
||||
#define DRM_IOC_VOID _IOC_NONE
|
||||
#define DRM_IOC_READ _IOC_READ
|
||||
#define DRM_IOC_WRITE _IOC_WRITE
|
||||
#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE
|
||||
#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && defined(IN_MODULE)
|
||||
/* Prevent name collision when including sys/ioccom.h */
|
||||
#undef ioctl
|
||||
#include <sys/ioccom.h>
|
||||
#define ioctl(a,b,c) xf86ioctl(a,b,c)
|
||||
#else
|
||||
#include <sys/ioccom.h>
|
||||
#endif /* __FreeBSD__ && xf86ioctl */
|
||||
#define DRM_IOCTL_NR(n) ((n) & 0xff)
|
||||
#define DRM_IOC_VOID IOC_VOID
|
||||
#define DRM_IOC_READ IOC_OUT
|
||||
#define DRM_IOC_WRITE IOC_IN
|
||||
#define DRM_IOC_READWRITE IOC_INOUT
|
||||
#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
|
||||
#endif
|
||||
|
||||
#define XFREE86_VERSION(major,minor,patch,snap) \
|
||||
((major << 16) | (minor << 8) | patch)
|
||||
|
||||
#ifndef CONFIG_XFREE86_VERSION
|
||||
#define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0)
|
||||
#endif
|
||||
|
||||
#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
|
||||
#define DRM_PROC_DEVICES "/proc/devices"
|
||||
#define DRM_PROC_MISC "/proc/misc"
|
||||
#define DRM_PROC_DRM "/proc/drm"
|
||||
#define DRM_DEV_DRM "/dev/drm"
|
||||
#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
|
||||
#define DRM_DEV_UID 0
|
||||
#define DRM_DEV_GID 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
|
||||
#ifdef __OpenBSD__
|
||||
#define DRM_MAJOR 81
|
||||
#endif
|
||||
#if defined(__linux__) || defined(__NetBSD__)
|
||||
#define DRM_MAJOR 226
|
||||
#endif
|
||||
#define DRM_MAX_MINOR 15
|
||||
#endif
|
||||
#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
|
||||
#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
|
||||
#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
|
||||
#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
|
||||
|
||||
#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */
|
||||
#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */
|
||||
#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
|
||||
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
|
||||
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
|
||||
|
||||
#if defined(__linux__)
|
||||
typedef unsigned int drm_handle_t;
|
||||
#else
|
||||
typedef unsigned long drm_handle_t; /**< To mapped regions */
|
||||
#endif
|
||||
typedef unsigned int drm_context_t; /**< GLXContext handle */
|
||||
typedef unsigned int drm_drawable_t;
|
||||
typedef unsigned int drm_magic_t; /**< Magic for authentication */
|
||||
|
||||
/**
|
||||
* Cliprect.
|
||||
*
|
||||
* \warning If you change this structure, make sure you change
|
||||
* XF86DRIClipRectRec in the server as well
|
||||
*
|
||||
* \note KW: Actually it's illegal to change either for
|
||||
* backwards-compatibility reasons.
|
||||
*/
|
||||
typedef struct drm_clip_rect {
|
||||
unsigned short x1;
|
||||
unsigned short y1;
|
||||
unsigned short x2;
|
||||
unsigned short y2;
|
||||
} drm_clip_rect_t;
|
||||
|
||||
/**
|
||||
* Texture region,
|
||||
*/
|
||||
typedef struct drm_tex_region {
|
||||
unsigned char next;
|
||||
unsigned char prev;
|
||||
unsigned char in_use;
|
||||
unsigned char padding;
|
||||
unsigned int age;
|
||||
} drm_tex_region_t;
|
||||
|
||||
/**
|
||||
* Hardware lock.
|
||||
*
|
||||
* The lock structure is a simple cache-line aligned integer. To avoid
|
||||
* processor bus contention on a multiprocessor system, there should not be any
|
||||
* other data stored in the same cache line.
|
||||
*/
|
||||
typedef struct drm_hw_lock {
|
||||
__volatile__ unsigned int lock; /**< lock variable */
|
||||
char padding[60]; /**< Pad to cache line */
|
||||
} drm_hw_lock_t;
|
||||
|
||||
/* This is beyond ugly, and only works on GCC. However, it allows me to use
|
||||
* drm.h in places (i.e., in the X-server) where I can't use size_t. The real
|
||||
* fix is to use uint32_t instead of size_t, but that fix will break existing
|
||||
* LP64 (i.e., PowerPC64, SPARC64, IA-64, Alpha, etc.) systems. That *will*
|
||||
* eventually happen, though. I chose 'unsigned long' to be the fallback type
|
||||
* because that works on all the platforms I know about. Hopefully, the
|
||||
* real fix will happen before that bites us.
|
||||
*/
|
||||
|
||||
#ifdef __SIZE_TYPE__
|
||||
# define DRM_SIZE_T __SIZE_TYPE__
|
||||
#else
|
||||
# warning "__SIZE_TYPE__ not defined. Assuming sizeof(size_t) == sizeof(unsigned long)!"
|
||||
# define DRM_SIZE_T unsigned long
|
||||
#endif
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_VERSION ioctl argument type.
|
||||
*
|
||||
* \sa drmGetVersion().
|
||||
*/
|
||||
typedef struct drm_version {
|
||||
int version_major; /**< Major version */
|
||||
int version_minor; /**< Minor version */
|
||||
int version_patchlevel; /**< Patch level */
|
||||
DRM_SIZE_T name_len; /**< Length of name buffer */
|
||||
char __user *name; /**< Name of driver */
|
||||
DRM_SIZE_T date_len; /**< Length of date buffer */
|
||||
char __user *date; /**< User-space buffer to hold date */
|
||||
DRM_SIZE_T desc_len; /**< Length of desc buffer */
|
||||
char __user *desc; /**< User-space buffer to hold desc */
|
||||
} drm_version_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_UNIQUE ioctl argument type.
|
||||
*
|
||||
* \sa drmGetBusid() and drmSetBusId().
|
||||
*/
|
||||
typedef struct drm_unique {
|
||||
DRM_SIZE_T unique_len; /**< Length of unique */
|
||||
char __user *unique; /**< Unique name for driver instantiation */
|
||||
} drm_unique_t;
|
||||
|
||||
#undef DRM_SIZE_T
|
||||
|
||||
typedef struct drm_list {
|
||||
int count; /**< Length of user-space structures */
|
||||
drm_version_t __user *version;
|
||||
} drm_list_t;
|
||||
|
||||
typedef struct drm_block {
|
||||
int unused;
|
||||
} drm_block_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_CONTROL ioctl argument type.
|
||||
*
|
||||
* \sa drmCtlInstHandler() and drmCtlUninstHandler().
|
||||
*/
|
||||
typedef struct drm_control {
|
||||
enum {
|
||||
DRM_ADD_COMMAND,
|
||||
DRM_RM_COMMAND,
|
||||
DRM_INST_HANDLER,
|
||||
DRM_UNINST_HANDLER
|
||||
} func;
|
||||
int irq;
|
||||
} drm_control_t;
|
||||
|
||||
/**
|
||||
* Type of memory to map.
|
||||
*/
|
||||
typedef enum drm_map_type {
|
||||
_DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /**< no caching, no core dump */
|
||||
_DRM_SHM = 2, /**< shared, cached */
|
||||
_DRM_AGP = 3, /**< AGP/GART */
|
||||
_DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
|
||||
_DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */
|
||||
} drm_map_type_t;
|
||||
|
||||
/**
|
||||
* Memory mapping flags.
|
||||
*/
|
||||
typedef enum drm_map_flags {
|
||||
_DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
|
||||
_DRM_READ_ONLY = 0x02,
|
||||
_DRM_LOCKED = 0x04, /**< shared, cached, locked */
|
||||
_DRM_KERNEL = 0x08, /**< kernel requires access */
|
||||
_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
|
||||
_DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
|
||||
_DRM_REMOVABLE = 0x40 /**< Removable mapping */
|
||||
} drm_map_flags_t;
|
||||
|
||||
typedef struct drm_ctx_priv_map {
|
||||
unsigned int ctx_id; /**< Context requesting private mapping */
|
||||
void *handle; /**< Handle of map */
|
||||
} drm_ctx_priv_map_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
|
||||
* argument type.
|
||||
*
|
||||
* \sa drmAddMap().
|
||||
*/
|
||||
typedef struct drm_map {
|
||||
unsigned long offset; /**< Requested physical address (0 for SAREA)*/
|
||||
unsigned long size; /**< Requested physical size (bytes) */
|
||||
drm_map_type_t type; /**< Type of memory to map */
|
||||
drm_map_flags_t flags; /**< Flags */
|
||||
void *handle; /**< User-space: "Handle" to pass to mmap() */
|
||||
/**< Kernel-space: kernel-virtual address */
|
||||
int mtrr; /**< MTRR slot used */
|
||||
/* Private data */
|
||||
} drm_map_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_CLIENT ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_client {
|
||||
int idx; /**< Which client desired? */
|
||||
int auth; /**< Is client authenticated? */
|
||||
unsigned long pid; /**< Process ID */
|
||||
unsigned long uid; /**< User ID */
|
||||
unsigned long magic; /**< Magic */
|
||||
unsigned long iocs; /**< Ioctl count */
|
||||
} drm_client_t;
|
||||
|
||||
typedef enum {
|
||||
_DRM_STAT_LOCK,
|
||||
_DRM_STAT_OPENS,
|
||||
_DRM_STAT_CLOSES,
|
||||
_DRM_STAT_IOCTLS,
|
||||
_DRM_STAT_LOCKS,
|
||||
_DRM_STAT_UNLOCKS,
|
||||
_DRM_STAT_VALUE, /**< Generic value */
|
||||
_DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */
|
||||
_DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */
|
||||
|
||||
_DRM_STAT_IRQ, /**< IRQ */
|
||||
_DRM_STAT_PRIMARY, /**< Primary DMA bytes */
|
||||
_DRM_STAT_SECONDARY, /**< Secondary DMA bytes */
|
||||
_DRM_STAT_DMA, /**< DMA */
|
||||
_DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
|
||||
_DRM_STAT_MISSED /**< Missed DMA opportunity */
|
||||
/* Add to the *END* of the list */
|
||||
} drm_stat_type_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_STATS ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_stats {
|
||||
unsigned long count;
|
||||
struct {
|
||||
unsigned long value;
|
||||
drm_stat_type_t type;
|
||||
} data[15];
|
||||
} drm_stats_t;
|
||||
|
||||
/**
|
||||
* Hardware locking flags.
|
||||
*/
|
||||
typedef enum drm_lock_flags {
|
||||
_DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
|
||||
_DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
|
||||
_DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
|
||||
_DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
|
||||
/* These *HALT* flags aren't supported yet
|
||||
-- they will be used to support the
|
||||
full-screen DGA-like mode. */
|
||||
_DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
|
||||
_DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
|
||||
} drm_lock_flags_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
|
||||
*
|
||||
* \sa drmGetLock() and drmUnlock().
|
||||
*/
|
||||
typedef struct drm_lock {
|
||||
int context;
|
||||
drm_lock_flags_t flags;
|
||||
} drm_lock_t;
|
||||
|
||||
/**
|
||||
* DMA flags
|
||||
*
|
||||
* \warning
|
||||
* These values \e must match xf86drm.h.
|
||||
*
|
||||
* \sa drm_dma.
|
||||
*/
|
||||
typedef enum drm_dma_flags {
|
||||
/* Flags for DMA buffer dispatch */
|
||||
_DRM_DMA_BLOCK = 0x01, /**<
|
||||
* Block until buffer dispatched.
|
||||
*
|
||||
* \note The buffer may not yet have
|
||||
* been processed by the hardware --
|
||||
* getting a hardware lock with the
|
||||
* hardware quiescent will ensure
|
||||
* that the buffer has been
|
||||
* processed.
|
||||
*/
|
||||
_DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
|
||||
_DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
|
||||
|
||||
/* Flags for DMA buffer request */
|
||||
_DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
|
||||
_DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
|
||||
_DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
|
||||
} drm_dma_flags_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
|
||||
*
|
||||
* \sa drmAddBufs().
|
||||
*/
|
||||
typedef struct drm_buf_desc {
|
||||
int count; /**< Number of buffers of this size */
|
||||
int size; /**< Size in bytes */
|
||||
int low_mark; /**< Low water mark */
|
||||
int high_mark; /**< High water mark */
|
||||
enum {
|
||||
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
|
||||
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
|
||||
_DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
|
||||
_DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */
|
||||
} flags;
|
||||
unsigned long agp_start; /**<
|
||||
* Start address of where the AGP buffers are
|
||||
* in the AGP aperture
|
||||
*/
|
||||
} drm_buf_desc_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_INFO_BUFS ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_buf_info {
|
||||
int count; /**< Number of buffers described in list */
|
||||
drm_buf_desc_t __user *list; /**< List of buffer descriptions */
|
||||
} drm_buf_info_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_FREE_BUFS ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_buf_free {
|
||||
int count;
|
||||
int __user *list;
|
||||
} drm_buf_free_t;
|
||||
|
||||
/**
|
||||
* Buffer information
|
||||
*
|
||||
* \sa drm_buf_map.
|
||||
*/
|
||||
typedef struct drm_buf_pub {
|
||||
int idx; /**< Index into the master buffer list */
|
||||
int total; /**< Buffer size */
|
||||
int used; /**< Amount of buffer in use (for DMA) */
|
||||
void __user *address; /**< Address of buffer */
|
||||
} drm_buf_pub_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_MAP_BUFS ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_buf_map {
|
||||
int count; /**< Length of the buffer list */
|
||||
#if defined(__cplusplus)
|
||||
void __user *c_virtual;
|
||||
#else
|
||||
void __user *virtual; /**< Mmap'd area in user-virtual */
|
||||
#endif
|
||||
drm_buf_pub_t __user *list; /**< Buffer information */
|
||||
} drm_buf_map_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_DMA ioctl argument type.
|
||||
*
|
||||
* Indices here refer to the offset into the buffer list in drm_buf_get.
|
||||
*
|
||||
* \sa drmDMA().
|
||||
*/
|
||||
typedef struct drm_dma {
|
||||
int context; /**< Context handle */
|
||||
int send_count; /**< Number of buffers to send */
|
||||
int __user *send_indices; /**< List of handles to buffers */
|
||||
int __user *send_sizes; /**< Lengths of data to send */
|
||||
drm_dma_flags_t flags; /**< Flags */
|
||||
int request_count; /**< Number of buffers requested */
|
||||
int request_size; /**< Desired size for buffers */
|
||||
int __user *request_indices; /**< Buffer information */
|
||||
int __user *request_sizes;
|
||||
int granted_count; /**< Number of buffers granted */
|
||||
} drm_dma_t;
|
||||
|
||||
typedef enum {
|
||||
_DRM_CONTEXT_PRESERVED = 0x01,
|
||||
_DRM_CONTEXT_2DONLY = 0x02
|
||||
} drm_ctx_flags_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_CTX ioctl argument type.
|
||||
*
|
||||
* \sa drmCreateContext() and drmDestroyContext().
|
||||
*/
|
||||
typedef struct drm_ctx {
|
||||
drm_context_t handle;
|
||||
drm_ctx_flags_t flags;
|
||||
} drm_ctx_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_RES_CTX ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_ctx_res {
|
||||
int count;
|
||||
drm_ctx_t __user *contexts;
|
||||
} drm_ctx_res_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_draw {
|
||||
drm_drawable_t handle;
|
||||
} drm_draw_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_auth {
|
||||
drm_magic_t magic;
|
||||
} drm_auth_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_IRQ_BUSID ioctl argument type.
|
||||
*
|
||||
* \sa drmGetInterruptFromBusID().
|
||||
*/
|
||||
typedef struct drm_irq_busid {
|
||||
int irq; /**< IRQ number */
|
||||
int busnum; /**< bus number */
|
||||
int devnum; /**< device number */
|
||||
int funcnum; /**< function number */
|
||||
} drm_irq_busid_t;
|
||||
|
||||
typedef enum {
|
||||
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
|
||||
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
|
||||
_DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
|
||||
} drm_vblank_seq_type_t;
|
||||
|
||||
#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
|
||||
|
||||
struct drm_wait_vblank_request {
|
||||
drm_vblank_seq_type_t type;
|
||||
unsigned int sequence;
|
||||
unsigned long signal;
|
||||
};
|
||||
|
||||
struct drm_wait_vblank_reply {
|
||||
drm_vblank_seq_type_t type;
|
||||
unsigned int sequence;
|
||||
long tval_sec;
|
||||
long tval_usec;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_WAIT_VBLANK ioctl argument type.
|
||||
*
|
||||
* \sa drmWaitVBlank().
|
||||
*/
|
||||
typedef union drm_wait_vblank {
|
||||
struct drm_wait_vblank_request request;
|
||||
struct drm_wait_vblank_reply reply;
|
||||
} drm_wait_vblank_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_ENABLE ioctl argument type.
|
||||
*
|
||||
* \sa drmAgpEnable().
|
||||
*/
|
||||
typedef struct drm_agp_mode {
|
||||
unsigned long mode; /**< AGP mode */
|
||||
} drm_agp_mode_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
|
||||
*
|
||||
* \sa drmAgpAlloc() and drmAgpFree().
|
||||
*/
|
||||
typedef struct drm_agp_buffer {
|
||||
unsigned long size; /**< In bytes -- will round to page boundary */
|
||||
unsigned long handle; /**< Used for binding / unbinding */
|
||||
unsigned long type; /**< Type of memory to allocate */
|
||||
unsigned long physical; /**< Physical used by i810 */
|
||||
} drm_agp_buffer_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
|
||||
*
|
||||
* \sa drmAgpBind() and drmAgpUnbind().
|
||||
*/
|
||||
typedef struct drm_agp_binding {
|
||||
unsigned long handle; /**< From drm_agp_buffer */
|
||||
unsigned long offset; /**< In bytes -- will round to page boundary */
|
||||
} drm_agp_binding_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_INFO ioctl argument type.
|
||||
*
|
||||
* \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
|
||||
* drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
|
||||
* drmAgpVendorId() and drmAgpDeviceId().
|
||||
*/
|
||||
typedef struct drm_agp_info {
|
||||
int agp_version_major;
|
||||
int agp_version_minor;
|
||||
unsigned long mode;
|
||||
unsigned long aperture_base; /**< physical address */
|
||||
unsigned long aperture_size; /**< bytes */
|
||||
unsigned long memory_allowed; /**< bytes */
|
||||
unsigned long memory_used;
|
||||
|
||||
/** \name PCI information */
|
||||
/*@{ */
|
||||
unsigned short id_vendor;
|
||||
unsigned short id_device;
|
||||
/*@} */
|
||||
} drm_agp_info_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_SG_ALLOC ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_scatter_gather {
|
||||
unsigned long size; /**< In bytes -- will round to page boundary */
|
||||
unsigned long handle; /**< Used for mapping / unmapping */
|
||||
} drm_scatter_gather_t;
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_SET_VERSION ioctl argument type.
|
||||
*/
|
||||
typedef struct drm_set_version {
|
||||
int drm_di_major;
|
||||
int drm_di_minor;
|
||||
int drm_dd_major;
|
||||
int drm_dd_minor;
|
||||
} drm_set_version_t;
|
||||
|
||||
/**
|
||||
* \name Ioctls Definitions
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
#define DRM_IOCTL_BASE 'd'
|
||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
|
||||
#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type)
|
||||
#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
|
||||
|
||||
#define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t)
|
||||
#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
|
||||
#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
|
||||
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
|
||||
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
|
||||
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
|
||||
#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t)
|
||||
#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, drm_set_version_t)
|
||||
|
||||
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
|
||||
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
|
||||
#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, drm_block_t)
|
||||
#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, drm_block_t)
|
||||
#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, drm_control_t)
|
||||
#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, drm_map_t)
|
||||
#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, drm_buf_desc_t)
|
||||
#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, drm_buf_desc_t)
|
||||
#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm_buf_info_t)
|
||||
#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm_buf_map_t)
|
||||
#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm_buf_free_t)
|
||||
|
||||
#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, drm_map_t)
|
||||
|
||||
#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, drm_ctx_priv_map_t)
|
||||
#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, drm_ctx_priv_map_t)
|
||||
|
||||
#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, drm_ctx_t)
|
||||
#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, drm_ctx_t)
|
||||
#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, drm_ctx_t)
|
||||
#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, drm_ctx_t)
|
||||
#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t)
|
||||
#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, drm_ctx_t)
|
||||
#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t)
|
||||
#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, drm_draw_t)
|
||||
#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, drm_draw_t)
|
||||
#define DRM_IOCTL_DMA DRM_IOWR(0x29, drm_dma_t)
|
||||
#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, drm_lock_t)
|
||||
#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t)
|
||||
#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t)
|
||||
|
||||
#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
|
||||
#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
|
||||
#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t)
|
||||
#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t)
|
||||
#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t)
|
||||
#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t)
|
||||
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
|
||||
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
|
||||
|
||||
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
|
||||
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
|
||||
|
||||
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Device specific ioctls should only be in their respective headers
|
||||
* The device specific ioctl range is from 0x40 to 0x79.
|
||||
*
|
||||
* \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
|
||||
* drmCommandReadWrite().
|
||||
*/
|
||||
#define DRM_COMMAND_BASE 0x40
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,474 @@
|
|||
/* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*-
|
||||
* Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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.
|
||||
*
|
||||
* Author:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_agpsupport.c,v 1.5 2006/04/09 20:45:44 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <pci/agpreg.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#endif
|
||||
|
||||
/* Returns 1 if AGP or 0 if not. */
|
||||
static int
|
||||
drm_device_find_capability(drm_device_t *dev, int cap)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
#if __FreeBSD_version >= 700010
|
||||
|
||||
return (pci_find_extcap(dev->device, cap, NULL) == 0);
|
||||
#else
|
||||
/* Code taken from agp.c. IWBNI that was a public interface. */
|
||||
u_int32_t status;
|
||||
u_int8_t ptr, next;
|
||||
|
||||
/*
|
||||
* Check the CAP_LIST bit of the PCI status register first.
|
||||
*/
|
||||
status = pci_read_config(dev->device, PCIR_STATUS, 2);
|
||||
if (!(status & 0x10))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Traverse the capabilities list.
|
||||
*/
|
||||
for (ptr = pci_read_config(dev->device, AGP_CAPPTR, 1);
|
||||
ptr != 0;
|
||||
ptr = next) {
|
||||
u_int32_t capid = pci_read_config(dev->device, ptr, 4);
|
||||
next = AGP_CAPID_GET_NEXT_PTR(capid);
|
||||
|
||||
/*
|
||||
* If this capability entry ID is cap, then we are done.
|
||||
*/
|
||||
if (AGP_CAPID_GET_CAP_ID(capid) == cap)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
#else
|
||||
#ifdef __NetBSD__
|
||||
return pci_get_capability(dev->pa.pa_pc, dev->pa.pa_tag, cap,
|
||||
NULL, NULL);
|
||||
#endif
|
||||
/* XXX: fill me in for non-FreeBSD */
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int drm_device_is_agp(drm_device_t *dev)
|
||||
{
|
||||
if (dev->driver.device_is_agp != NULL) {
|
||||
int ret;
|
||||
|
||||
/* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely
|
||||
* AGP, 2 = fall back to PCI capability
|
||||
*/
|
||||
ret = (*dev->driver.device_is_agp)(dev);
|
||||
if (ret != DRM_MIGHT_BE_AGP)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (drm_device_find_capability(dev, PCIY_AGP));
|
||||
}
|
||||
|
||||
int drm_device_is_pcie(drm_device_t *dev)
|
||||
{
|
||||
return (drm_device_find_capability(dev, PCIY_EXPRESS));
|
||||
}
|
||||
|
||||
int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info)
|
||||
{
|
||||
struct agp_info *kern;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
kern = &dev->agp->info;
|
||||
agp_get_info(dev->agp->agpdev, kern);
|
||||
info->agp_version_major = 1;
|
||||
info->agp_version_minor = 0;
|
||||
info->mode = kern->ai_mode;
|
||||
info->aperture_base = kern->ai_aperture_base;
|
||||
info->aperture_size = kern->ai_aperture_size;
|
||||
info->memory_allowed = kern->ai_memory_allowed;
|
||||
info->memory_used = kern->ai_memory_used;
|
||||
info->id_vendor = kern->ai_devid & 0xffff;
|
||||
info->id_device = kern->ai_devid >> 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_info_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
int err;
|
||||
drm_agp_info_t info;
|
||||
DRM_DEVICE;
|
||||
|
||||
err = drm_agp_info(dev, &info);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
*(drm_agp_info_t *) data = info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_acquire_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
|
||||
return drm_agp_acquire(dev);
|
||||
}
|
||||
|
||||
int drm_agp_acquire(drm_device_t *dev)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
if (!dev->agp || dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
retcode = agp_acquire(dev->agp->agpdev);
|
||||
if (retcode)
|
||||
return retcode;
|
||||
|
||||
dev->agp->acquired = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_release_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
|
||||
return drm_agp_release(dev);
|
||||
}
|
||||
|
||||
int drm_agp_release(drm_device_t * dev)
|
||||
{
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
agp_release(dev->agp->agpdev);
|
||||
dev->agp->acquired = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
|
||||
{
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
dev->agp->mode = mode.mode;
|
||||
agp_enable(dev->agp->agpdev, mode.mode);
|
||||
dev->agp->base = dev->agp->info.ai_aperture_base;
|
||||
dev->agp->enabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_enable_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
drm_agp_mode_t mode;
|
||||
DRM_DEVICE;
|
||||
|
||||
mode = *(drm_agp_mode_t *) data;
|
||||
|
||||
return drm_agp_enable(dev, mode);
|
||||
}
|
||||
|
||||
int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
void *handle;
|
||||
unsigned long pages;
|
||||
u_int32_t type;
|
||||
struct agp_memory_info info;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
entry = malloc(sizeof(*entry), M_DRM, M_NOWAIT | M_ZERO);
|
||||
if (entry == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
type = (u_int32_t) request->type;
|
||||
|
||||
DRM_UNLOCK();
|
||||
handle = drm_agp_allocate_memory(pages, type);
|
||||
DRM_LOCK();
|
||||
if (handle == NULL) {
|
||||
free(entry, M_DRM);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
entry->handle = handle;
|
||||
entry->bound = 0;
|
||||
entry->pages = pages;
|
||||
entry->prev = NULL;
|
||||
entry->next = dev->agp->memory;
|
||||
if (dev->agp->memory)
|
||||
dev->agp->memory->prev = entry;
|
||||
dev->agp->memory = entry;
|
||||
|
||||
agp_memory_info(dev->agp->agpdev, entry->handle, &info);
|
||||
|
||||
request->handle = (unsigned long) entry->handle;
|
||||
request->physical = info.ami_physical;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_alloc_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_agp_buffer_t request;
|
||||
int retcode;
|
||||
|
||||
request = *(drm_agp_buffer_t *) data;
|
||||
|
||||
DRM_LOCK();
|
||||
retcode = drm_agp_alloc(dev, &request);
|
||||
DRM_UNLOCK();
|
||||
|
||||
*(drm_agp_buffer_t *) data = request;
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static drm_agp_mem_t * drm_agp_lookup_entry(drm_device_t *dev, void *handle)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
|
||||
for (entry = dev->agp->memory; entry; entry = entry->next) {
|
||||
if (entry->handle == handle) return entry;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
int retcode;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
entry = drm_agp_lookup_entry(dev, (void *)request->handle);
|
||||
if (entry == NULL || !entry->bound)
|
||||
return EINVAL;
|
||||
|
||||
DRM_UNLOCK();
|
||||
retcode = drm_agp_unbind_memory(entry->handle);
|
||||
DRM_LOCK();
|
||||
|
||||
if (retcode == 0)
|
||||
entry->bound = 0;
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_agp_unbind_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_agp_binding_t request;
|
||||
int retcode;
|
||||
|
||||
request = *(drm_agp_binding_t *) data;
|
||||
|
||||
DRM_LOCK();
|
||||
retcode = drm_agp_unbind(dev, &request);
|
||||
DRM_UNLOCK();
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
int retcode;
|
||||
int page;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
DRM_DEBUG("agp_bind, page_size=%x\n", PAGE_SIZE);
|
||||
|
||||
entry = drm_agp_lookup_entry(dev, (void *)request->handle);
|
||||
if (entry == NULL || entry->bound)
|
||||
return EINVAL;
|
||||
|
||||
page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
DRM_UNLOCK();
|
||||
retcode = drm_agp_bind_memory(entry->handle, page);
|
||||
DRM_LOCK();
|
||||
if (retcode == 0)
|
||||
entry->bound = dev->agp->base + (page << PAGE_SHIFT);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_agp_bind_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_agp_binding_t request;
|
||||
int retcode;
|
||||
|
||||
request = *(drm_agp_binding_t *) data;
|
||||
|
||||
DRM_LOCK();
|
||||
retcode = drm_agp_bind(dev, &request);
|
||||
DRM_UNLOCK();
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
entry = drm_agp_lookup_entry(dev, (void*)request->handle);
|
||||
if (entry == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (entry->prev)
|
||||
entry->prev->next = entry->next;
|
||||
else
|
||||
dev->agp->memory = entry->next;
|
||||
if (entry->next)
|
||||
entry->next->prev = entry->prev;
|
||||
|
||||
DRM_UNLOCK();
|
||||
if (entry->bound)
|
||||
drm_agp_unbind_memory(entry->handle);
|
||||
drm_agp_free_memory(entry->handle);
|
||||
DRM_LOCK();
|
||||
|
||||
free(entry, M_DRM);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int drm_agp_free_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_agp_buffer_t request;
|
||||
int retcode;
|
||||
|
||||
request = *(drm_agp_buffer_t *) data;
|
||||
|
||||
DRM_LOCK();
|
||||
retcode = drm_agp_free(dev, &request);
|
||||
DRM_UNLOCK();
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
drm_agp_head_t *drm_agp_init(void)
|
||||
{
|
||||
device_t agpdev;
|
||||
drm_agp_head_t *head = NULL;
|
||||
int agp_available = 1;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev)
|
||||
agp_available = 0;
|
||||
|
||||
DRM_DEBUG("agp_available = %d\n", agp_available);
|
||||
|
||||
if (agp_available) {
|
||||
head = malloc(sizeof(*head), M_DRM, M_NOWAIT | M_ZERO);
|
||||
if (head == NULL)
|
||||
return NULL;
|
||||
head->agpdev = agpdev;
|
||||
agp_get_info(agpdev, &head->info);
|
||||
head->memory = NULL;
|
||||
DRM_INFO("AGP at 0x%08lx %dMB\n",
|
||||
(long)head->info.ai_aperture_base,
|
||||
(int)(head->info.ai_aperture_size >> 20));
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
void *drm_agp_allocate_memory(size_t pages, u32 type)
|
||||
{
|
||||
device_t agpdev;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev)
|
||||
return NULL;
|
||||
|
||||
return agp_alloc_memory(agpdev, type, pages << AGP_PAGE_SHIFT);
|
||||
}
|
||||
|
||||
int drm_agp_free_memory(void *handle)
|
||||
{
|
||||
device_t agpdev;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev || !handle)
|
||||
return 0;
|
||||
|
||||
agp_free_memory(agpdev, handle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int drm_agp_bind_memory(void *handle, off_t start)
|
||||
{
|
||||
device_t agpdev;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev || !handle)
|
||||
return EINVAL;
|
||||
|
||||
return agp_bind_memory(agpdev, handle, start * PAGE_SIZE);
|
||||
}
|
||||
|
||||
int drm_agp_unbind_memory(void *handle)
|
||||
{
|
||||
device_t agpdev;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev || !handle)
|
||||
return EINVAL;
|
||||
|
||||
return agp_unbind_memory(agpdev, handle);
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/**
|
||||
* \file drm_atomic.h
|
||||
* Atomic operations used in the DRM which may or may not be provided by the OS.
|
||||
*
|
||||
* \author Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright 2004 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_atomic.h,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
/* Many of these implementations are rather fake, but good enough. */
|
||||
|
||||
typedef u_int32_t atomic_t;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define atomic_set(p, v) (*(p) = (v))
|
||||
#define atomic_read(p) (*(p))
|
||||
#define atomic_inc(p) atomic_add_int(p, 1)
|
||||
#define atomic_dec(p) atomic_subtract_int(p, 1)
|
||||
#define atomic_add(n, p) atomic_add_int(p, n)
|
||||
#define atomic_sub(n, p) atomic_subtract_int(p, n)
|
||||
#else /* __FreeBSD__ */
|
||||
/* FIXME */
|
||||
#define atomic_set(p, v) (*(p) = (v))
|
||||
#define atomic_read(p) (*(p))
|
||||
#define atomic_inc(p) (*(p) += 1)
|
||||
#define atomic_dec(p) (*(p) -= 1)
|
||||
#define atomic_add(n, p) (*(p) += (n))
|
||||
#define atomic_sub(n, p) (*(p) -= (n))
|
||||
/* FIXME */
|
||||
#define atomic_add_int(p, v) *(p) += v
|
||||
#define atomic_subtract_int(p, v) *(p) -= v
|
||||
#define atomic_set_int(p, bits) *(p) |= (bits)
|
||||
#define atomic_clear_int(p, bits) *(p) &= ~(bits)
|
||||
#endif /* !__FreeBSD__ */
|
||||
|
||||
#if !defined(__FreeBSD_version) || (__FreeBSD_version < 500000)
|
||||
#if defined(__i386__)
|
||||
/* The extra atomic functions from 5.0 haven't been merged to 4.x */
|
||||
static __inline int
|
||||
atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
|
||||
{
|
||||
int res = exp;
|
||||
|
||||
__asm __volatile (
|
||||
" lock ; "
|
||||
" cmpxchgl %1,%2 ; "
|
||||
" setz %%al ; "
|
||||
" movzbl %%al,%0 ; "
|
||||
"1: "
|
||||
"# atomic_cmpset_int"
|
||||
: "+a" (res) /* 0 (result) */
|
||||
: "r" (src), /* 1 */
|
||||
"m" (*(dst)) /* 2 */
|
||||
: "memory");
|
||||
|
||||
return (res);
|
||||
}
|
||||
#else /* __i386__ */
|
||||
static __inline int
|
||||
atomic_cmpset_int(__volatile__ int *dst, int old, int new)
|
||||
{
|
||||
int s = splhigh();
|
||||
if (*dst==old) {
|
||||
*dst = new;
|
||||
splx(s);
|
||||
return 1;
|
||||
}
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
#endif /* !__i386__ */
|
||||
#endif /* !__FreeBSD_version || __FreeBSD_version < 500000 */
|
||||
|
||||
static __inline atomic_t
|
||||
test_and_set_bit(int b, volatile void *p)
|
||||
{
|
||||
int s = splhigh();
|
||||
unsigned int m = 1<<b;
|
||||
unsigned int r = *(volatile int *)p & m;
|
||||
*(volatile int *)p |= m;
|
||||
splx(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
clear_bit(int b, volatile void *p)
|
||||
{
|
||||
atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
|
||||
}
|
||||
|
||||
static __inline void
|
||||
set_bit(int b, volatile void *p)
|
||||
{
|
||||
atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
test_bit(int b, volatile void *p)
|
||||
{
|
||||
return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
find_first_zero_bit(volatile void *p, int maxbit)
|
||||
{
|
||||
int b;
|
||||
volatile int *ptr = (volatile int *)p;
|
||||
|
||||
for (b = 0; b < maxbit; b += 32) {
|
||||
if (ptr[b >> 5] != ~0) {
|
||||
for (;;) {
|
||||
if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0)
|
||||
return b;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxbit;
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_auth.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
static int drm_hash_magic(drm_magic_t magic)
|
||||
{
|
||||
return magic & (DRM_HASH_SIZE-1);
|
||||
}
|
||||
|
||||
static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_file_t *retval = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash;
|
||||
|
||||
hash = drm_hash_magic(magic);
|
||||
|
||||
DRM_LOCK();
|
||||
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
retval = pt->priv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
|
||||
{
|
||||
int hash;
|
||||
drm_magic_entry_t *entry;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
hash = drm_hash_magic(magic);
|
||||
entry = malloc(sizeof(*entry), M_DRM, M_ZERO | M_NOWAIT);
|
||||
if (!entry) return DRM_ERR(ENOMEM);
|
||||
entry->magic = magic;
|
||||
entry->priv = priv;
|
||||
entry->next = NULL;
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->magiclist[hash].tail) {
|
||||
dev->magiclist[hash].tail->next = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
} else {
|
||||
dev->magiclist[hash].head = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_magic_entry_t *prev = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
hash = drm_hash_magic(magic);
|
||||
|
||||
DRM_LOCK();
|
||||
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
if (dev->magiclist[hash].head == pt) {
|
||||
dev->magiclist[hash].head = pt->next;
|
||||
}
|
||||
if (dev->magiclist[hash].tail == pt) {
|
||||
dev->magiclist[hash].tail = prev;
|
||||
}
|
||||
if (prev) {
|
||||
prev->next = pt->next;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
free(pt, M_DRM);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
int drm_getmagic(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
static drm_magic_t sequence = 0;
|
||||
drm_auth_t auth;
|
||||
drm_file_t *priv;
|
||||
|
||||
DRM_LOCK();
|
||||
#ifdef __FreeBSD__
|
||||
priv = drm_find_file_by_proc(dev, p);
|
||||
#elif defined(__NetBSD__)
|
||||
priv = drm_find_file_by_proc(dev, p->l_proc);
|
||||
#endif
|
||||
DRM_UNLOCK();
|
||||
if (priv == NULL) {
|
||||
DRM_ERROR("can't find authenticator\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Find unique magic */
|
||||
if (priv->magic) {
|
||||
auth.magic = priv->magic;
|
||||
} else {
|
||||
do {
|
||||
int old = sequence;
|
||||
|
||||
auth.magic = old+1;
|
||||
|
||||
if (!atomic_cmpset_int(&sequence, old, auth.magic))
|
||||
continue;
|
||||
} while (drm_find_file(dev, auth.magic));
|
||||
priv->magic = auth.magic;
|
||||
drm_add_magic(dev, priv, auth.magic);
|
||||
}
|
||||
|
||||
DRM_DEBUG("%u\n", auth.magic);
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL((drm_auth_t *)data, auth, sizeof(auth));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_authmagic(DRM_IOCTL_ARGS)
|
||||
{
|
||||
drm_auth_t auth;
|
||||
drm_file_t *file;
|
||||
DRM_DEVICE;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(auth, (drm_auth_t *)data, sizeof(auth));
|
||||
|
||||
DRM_DEBUG("%u\n", auth.magic);
|
||||
|
||||
if ((file = drm_find_file(dev, auth.magic))) {
|
||||
file->authenticated = 1;
|
||||
drm_remove_magic(dev, auth.magic);
|
||||
return 0;
|
||||
}
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,350 @@
|
|||
/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
|
||||
* Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_context.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/* ================================================================
|
||||
* Context bitmap support
|
||||
*/
|
||||
|
||||
void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle)
|
||||
{
|
||||
if (ctx_handle < 0 || ctx_handle >= DRM_MAX_CTXBITMAP ||
|
||||
dev->ctx_bitmap == NULL) {
|
||||
DRM_ERROR("Attempt to free invalid context handle: %d\n",
|
||||
ctx_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_LOCK();
|
||||
clear_bit(ctx_handle, dev->ctx_bitmap);
|
||||
dev->context_sareas[ctx_handle] = NULL;
|
||||
DRM_UNLOCK();
|
||||
return;
|
||||
}
|
||||
|
||||
int drm_ctxbitmap_next(drm_device_t *dev)
|
||||
{
|
||||
int bit;
|
||||
|
||||
if (dev->ctx_bitmap == NULL)
|
||||
return -1;
|
||||
|
||||
DRM_LOCK();
|
||||
bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
|
||||
if (bit >= DRM_MAX_CTXBITMAP) {
|
||||
DRM_UNLOCK();
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_bit(bit, dev->ctx_bitmap);
|
||||
DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
|
||||
if ((bit+1) > dev->max_context) {
|
||||
dev->max_context = (bit+1);
|
||||
if (dev->context_sareas != NULL) {
|
||||
drm_local_map_t **ctx_sareas;
|
||||
|
||||
ctx_sareas = realloc(dev->context_sareas,
|
||||
dev->max_context * sizeof(*dev->context_sareas),
|
||||
M_DRM, M_NOWAIT);
|
||||
if (ctx_sareas == NULL) {
|
||||
clear_bit(bit, dev->ctx_bitmap);
|
||||
DRM_UNLOCK();
|
||||
return -1;
|
||||
}
|
||||
dev->context_sareas = ctx_sareas;
|
||||
dev->context_sareas[bit] = NULL;
|
||||
} else {
|
||||
/* max_context == 1 at this point */
|
||||
dev->context_sareas = malloc(dev->max_context *
|
||||
sizeof(*dev->context_sareas), M_DRM, M_NOWAIT);
|
||||
if (dev->context_sareas == NULL) {
|
||||
clear_bit(bit, dev->ctx_bitmap);
|
||||
DRM_UNLOCK();
|
||||
return -1;
|
||||
}
|
||||
dev->context_sareas[bit] = NULL;
|
||||
}
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
return bit;
|
||||
}
|
||||
|
||||
int drm_ctxbitmap_init(drm_device_t *dev)
|
||||
{
|
||||
int i;
|
||||
int temp;
|
||||
|
||||
DRM_LOCK();
|
||||
dev->ctx_bitmap = malloc(PAGE_SIZE, M_DRM, M_NOWAIT | M_ZERO);
|
||||
if ( dev->ctx_bitmap == NULL ) {
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
dev->context_sareas = NULL;
|
||||
dev->max_context = -1;
|
||||
DRM_UNLOCK();
|
||||
|
||||
for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
|
||||
temp = drm_ctxbitmap_next(dev);
|
||||
DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drm_ctxbitmap_cleanup(drm_device_t *dev)
|
||||
{
|
||||
DRM_LOCK();
|
||||
if (dev->context_sareas != NULL)
|
||||
free(dev->context_sareas, M_DRM);
|
||||
free(dev->ctx_bitmap, M_DRM);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Per Context SAREA Support
|
||||
*/
|
||||
|
||||
int drm_getsareactx( DRM_IOCTL_ARGS )
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_ctx_priv_map_t request;
|
||||
drm_local_map_t *map;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
|
||||
sizeof(request) );
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
map = dev->context_sareas[request.ctx_id];
|
||||
DRM_UNLOCK();
|
||||
|
||||
request.handle = map->handle;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_ctx_priv_map_t *)data, request, sizeof(request) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_setsareactx( DRM_IOCTL_ARGS )
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_ctx_priv_map_t request;
|
||||
drm_local_map_t *map = NULL;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
|
||||
sizeof(request) );
|
||||
|
||||
DRM_LOCK();
|
||||
TAILQ_FOREACH(map, &dev->maplist, link) {
|
||||
if (map->handle == request.handle) {
|
||||
if (dev->max_context < 0)
|
||||
goto bad;
|
||||
if (request.ctx_id >= (unsigned) dev->max_context)
|
||||
goto bad;
|
||||
dev->context_sareas[request.ctx_id] = map;
|
||||
DRM_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bad:
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* The actual DRM context handling routines
|
||||
*/
|
||||
|
||||
int drm_context_switch(drm_device_t *dev, int old, int new)
|
||||
{
|
||||
if ( test_and_set_bit( 0, &dev->context_flag ) ) {
|
||||
DRM_ERROR( "Reentering -- FIXME\n" );
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
|
||||
DRM_DEBUG( "Context switch from %d to %d\n", old, new );
|
||||
|
||||
if ( new == dev->last_context ) {
|
||||
clear_bit( 0, &dev->context_flag );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_context_switch_complete(drm_device_t *dev, int new)
|
||||
{
|
||||
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
|
||||
|
||||
if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
|
||||
DRM_ERROR( "Lock isn't held after context switch\n" );
|
||||
}
|
||||
|
||||
/* If a context switch is ever initiated
|
||||
when the kernel holds the lock, release
|
||||
that lock here. */
|
||||
clear_bit( 0, &dev->context_flag );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_resctx(DRM_IOCTL_ARGS)
|
||||
{
|
||||
drm_ctx_res_t res;
|
||||
drm_ctx_t ctx;
|
||||
int i;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( res, (drm_ctx_res_t *)data, sizeof(res) );
|
||||
|
||||
if ( res.count >= DRM_RESERVED_CONTEXTS ) {
|
||||
bzero(&ctx, sizeof(ctx));
|
||||
for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
|
||||
ctx.handle = i;
|
||||
if ( DRM_COPY_TO_USER( &res.contexts[i],
|
||||
&ctx, sizeof(ctx) ) )
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
}
|
||||
res.count = DRM_RESERVED_CONTEXTS;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_ctx_res_t *)data, res, sizeof(res) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_addctx(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
|
||||
|
||||
ctx.handle = drm_ctxbitmap_next(dev);
|
||||
if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
|
||||
/* Skip kernel's context and get a new one. */
|
||||
ctx.handle = drm_ctxbitmap_next(dev);
|
||||
}
|
||||
DRM_DEBUG( "%d\n", ctx.handle );
|
||||
if ( ctx.handle == -1 ) {
|
||||
DRM_DEBUG( "Not enough free contexts.\n" );
|
||||
/* Should this return -EBUSY instead? */
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
if (dev->driver.context_ctor && ctx.handle != DRM_KERNEL_CONTEXT) {
|
||||
DRM_LOCK();
|
||||
dev->driver.context_ctor(dev, ctx.handle);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_modctx(DRM_IOCTL_ARGS)
|
||||
{
|
||||
/* This does nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_getctx(DRM_IOCTL_ARGS)
|
||||
{
|
||||
drm_ctx_t ctx;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
|
||||
|
||||
/* This is 0, because we don't handle any context flags */
|
||||
ctx.flags = 0;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_switchctx(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
|
||||
|
||||
DRM_DEBUG( "%d\n", ctx.handle );
|
||||
return drm_context_switch(dev, dev->last_context, ctx.handle);
|
||||
}
|
||||
|
||||
int drm_newctx(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
|
||||
|
||||
DRM_DEBUG( "%d\n", ctx.handle );
|
||||
drm_context_switch_complete(dev, ctx.handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_rmctx(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_ctx_t ctx;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
|
||||
|
||||
DRM_DEBUG( "%d\n", ctx.handle );
|
||||
if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
|
||||
if (dev->driver.context_dtor) {
|
||||
DRM_LOCK();
|
||||
dev->driver.context_dtor(dev, ctx.handle);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
drm_ctxbitmap_free(dev, ctx.handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
|
||||
* Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_dma.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
int drm_dma_setup(drm_device_t *dev)
|
||||
{
|
||||
|
||||
dev->dma = malloc(sizeof(*dev->dma), M_DRM, M_NOWAIT | M_ZERO);
|
||||
if (dev->dma == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
DRM_SPININIT(dev->dma_lock, "drmdma");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drm_dma_takedown(drm_device_t *dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i, j;
|
||||
|
||||
if (dma == NULL)
|
||||
return;
|
||||
|
||||
/* Clear dma buffers */
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
if (dma->bufs[i].seg_count) {
|
||||
DRM_DEBUG("order %d: buf_count = %d,"
|
||||
" seg_count = %d\n",
|
||||
i,
|
||||
dma->bufs[i].buf_count,
|
||||
dma->bufs[i].seg_count);
|
||||
for (j = 0; j < dma->bufs[i].seg_count; j++) {
|
||||
drm_pci_free(dev, dma->bufs[i].seglist[j]);
|
||||
}
|
||||
free(dma->bufs[i].seglist, M_DRM);
|
||||
}
|
||||
|
||||
if (dma->bufs[i].buf_count) {
|
||||
for (j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
free(dma->bufs[i].buflist[j].dev_private,
|
||||
M_DRM);
|
||||
}
|
||||
free(dma->bufs[i].buflist, M_DRM);
|
||||
}
|
||||
}
|
||||
|
||||
free(dma->buflist, M_DRM);
|
||||
free(dma->pagelist, M_DRM);
|
||||
free(dev->dma, M_DRM);
|
||||
dev->dma = NULL;
|
||||
DRM_SPINUNINIT(dev->dma_lock);
|
||||
}
|
||||
|
||||
|
||||
void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
|
||||
{
|
||||
if (!buf) return;
|
||||
|
||||
buf->pending = 0;
|
||||
buf->filp = NULL;
|
||||
buf->used = 0;
|
||||
}
|
||||
|
||||
void drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i;
|
||||
|
||||
if (!dma) return;
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (dma->buflist[i]->filp == filp) {
|
||||
switch (dma->buflist[i]->list) {
|
||||
case DRM_LIST_NONE:
|
||||
drm_free_buffer(dev, dma->buflist[i]);
|
||||
break;
|
||||
case DRM_LIST_WAIT:
|
||||
dma->buflist[i]->list = DRM_LIST_RECLAIM;
|
||||
break;
|
||||
default:
|
||||
/* Buffer already on hardware. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Call into the driver-specific DMA handler */
|
||||
int drm_dma(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
|
||||
if (dev->driver.dma_ioctl) {
|
||||
return dev->driver.dma_ioctl(kdev, cmd, data, flags, p, filp);
|
||||
} else {
|
||||
DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_drawable.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
int drm_adddraw(DRM_IOCTL_ARGS)
|
||||
{
|
||||
drm_draw_t draw;
|
||||
|
||||
draw.handle = 0; /* NOOP */
|
||||
DRM_DEBUG("%d\n", draw.handle);
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_draw_t *)data, draw, sizeof(draw) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_rmdraw(DRM_IOCTL_ARGS)
|
||||
{
|
||||
return 0; /* NOOP */
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,139 @@
|
|||
/* drm_fops.h -- File operations for DRM -*- linux-c -*-
|
||||
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Daryll Strauss <daryll@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_fops.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
drm_file_t *drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p)
|
||||
{
|
||||
#if __FreeBSD_version >= 500021
|
||||
uid_t uid = p->td_ucred->cr_svuid;
|
||||
pid_t pid = p->td_proc->p_pid;
|
||||
#elif defined(__NetBSD__)
|
||||
uid_t uid = kauth_cred_getsvuid(p->p_cred);
|
||||
pid_t pid = p->p_pid;
|
||||
#else
|
||||
uid_t uid = p->p_cred->p_svuid;
|
||||
pid_t pid = p->p_pid;
|
||||
#endif
|
||||
drm_file_t *priv;
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
TAILQ_FOREACH(priv, &dev->files, link)
|
||||
if (priv->pid == pid && priv->uid == uid)
|
||||
return priv;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* drm_open_helper is called whenever a process opens /dev/drm. */
|
||||
int drm_open_helper(DRM_CDEV kdev, int flags, int fmt, DRM_STRUCTPROC *p,
|
||||
drm_device_t *dev)
|
||||
{
|
||||
int m = minor(kdev);
|
||||
drm_file_t *priv;
|
||||
int retcode;
|
||||
|
||||
if (flags & O_EXCL)
|
||||
return EBUSY; /* No exclusive opens */
|
||||
dev->flags = flags;
|
||||
|
||||
DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m);
|
||||
|
||||
DRM_LOCK();
|
||||
priv = drm_find_file_by_proc(dev, p);
|
||||
if (priv) {
|
||||
priv->refs++;
|
||||
} else {
|
||||
priv = malloc(sizeof(*priv), M_DRM, M_NOWAIT | M_ZERO);
|
||||
if (priv == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
#if __FreeBSD_version >= 500000
|
||||
priv->uid = p->td_ucred->cr_svuid;
|
||||
priv->pid = p->td_proc->p_pid;
|
||||
#elif defined(__NetBSD__)
|
||||
priv->uid = kauth_cred_getsvuid(p->p_cred);
|
||||
priv->pid = p->p_pid;
|
||||
#else
|
||||
priv->uid = p->p_cred->p_svuid;
|
||||
priv->pid = p->p_pid;
|
||||
#endif
|
||||
|
||||
priv->refs = 1;
|
||||
priv->minor = m;
|
||||
priv->ioctl_count = 0;
|
||||
|
||||
/* for compatibility root is always authenticated */
|
||||
priv->authenticated = DRM_SUSER(p);
|
||||
|
||||
if (dev->driver.open) {
|
||||
retcode = dev->driver.open(dev, priv);
|
||||
if (retcode != 0) {
|
||||
free(priv, M_DRM);
|
||||
DRM_UNLOCK();
|
||||
return retcode;
|
||||
}
|
||||
}
|
||||
|
||||
/* first opener automatically becomes master */
|
||||
priv->master = TAILQ_EMPTY(&dev->files);
|
||||
|
||||
TAILQ_INSERT_TAIL(&dev->files, priv, link);
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
#ifdef __FreeBSD__
|
||||
kdev->si_drv1 = dev;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The drm_read and drm_poll are stubs to prevent spurious errors
|
||||
* on older X Servers (4.3.0 and earlier) */
|
||||
|
||||
int drm_read(DRM_CDEV kdev, struct uio *uio, int ioflag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_poll(DRM_CDEV kdev, int events, DRM_STRUCTCDEVPROC *p)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
/* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
|
||||
* Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_ioctl.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/*
|
||||
* Beginning in revision 1.1 of the DRM interface, getunique will return
|
||||
* a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
|
||||
* before setunique has been called. The format for the bus-specific part of
|
||||
* the unique is not defined for any other bus.
|
||||
*/
|
||||
int drm_getunique(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_unique_t u;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) );
|
||||
|
||||
if (u.unique_len >= dev->unique_len) {
|
||||
if (DRM_COPY_TO_USER(u.unique, dev->unique, dev->unique_len))
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
u.unique_len = dev->unique_len;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_unique_t *)data, u, sizeof(u) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Deprecated in DRM version 1.1, and will return EBUSY when setversion has
|
||||
* requested version 1.1 or greater.
|
||||
*/
|
||||
int drm_setunique(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_unique_t u;
|
||||
int domain = 0, bus = 0, slot = 0, func = 0, ret = 0;
|
||||
char *busid;
|
||||
#ifdef __NetBSD__
|
||||
return EOPNOTSUPP;
|
||||
#endif
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) );
|
||||
|
||||
/* Check and copy in the submitted Bus ID */
|
||||
if (!u.unique_len || u.unique_len > 1024)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
busid = malloc(u.unique_len + 1, M_DRM, M_WAITOK);
|
||||
if (busid == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
if (DRM_COPY_FROM_USER(busid, u.unique, u.unique_len)) {
|
||||
free(busid, M_DRM);
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
busid[u.unique_len] = '\0';
|
||||
|
||||
/* Return error if the busid submitted doesn't match the device's actual
|
||||
* busid.
|
||||
*/
|
||||
#ifdef __FreeBSD__
|
||||
ret = sscanf(busid, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
#endif
|
||||
if (ret != 3) {
|
||||
free(busid, M_DRM);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
domain = bus >> 8;
|
||||
bus &= 0xff;
|
||||
|
||||
if ((domain != dev->pci_domain) ||
|
||||
(bus != dev->pci_bus) ||
|
||||
(slot != dev->pci_slot) ||
|
||||
(func != dev->pci_func)) {
|
||||
free(busid, M_DRM);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* Actually set the device's busid now. */
|
||||
DRM_LOCK();
|
||||
if (dev->unique_len || dev->unique) {
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
|
||||
dev->unique_len = u.unique_len;
|
||||
dev->unique = busid;
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
drm_set_busid(drm_device_t *dev)
|
||||
{
|
||||
|
||||
DRM_LOCK();
|
||||
|
||||
if (dev->unique != NULL) {
|
||||
DRM_UNLOCK();
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
dev->unique_len = 20;
|
||||
dev->unique = malloc(dev->unique_len + 1, M_DRM, M_NOWAIT);
|
||||
if (dev->unique == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
|
||||
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_getmap(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_map_t map;
|
||||
drm_local_map_t *mapinlist;
|
||||
int idx;
|
||||
int i = 0;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( map, (drm_map_t *)data, sizeof(map) );
|
||||
|
||||
idx = map.offset;
|
||||
|
||||
DRM_LOCK();
|
||||
if (idx < 0) {
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
|
||||
if (i==idx) {
|
||||
map.offset = mapinlist->offset;
|
||||
map.size = mapinlist->size;
|
||||
map.type = mapinlist->type;
|
||||
map.flags = mapinlist->flags;
|
||||
map.handle = mapinlist->handle;
|
||||
map.mtrr = mapinlist->mtrr;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
if (mapinlist == NULL)
|
||||
return EINVAL;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_getclient(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_client_t client;
|
||||
drm_file_t *pt;
|
||||
int idx;
|
||||
int i = 0;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( client, (drm_client_t *)data, sizeof(client) );
|
||||
|
||||
idx = client.idx;
|
||||
DRM_LOCK();
|
||||
TAILQ_FOREACH(pt, &dev->files, link) {
|
||||
if (i==idx)
|
||||
{
|
||||
client.auth = pt->authenticated;
|
||||
client.pid = pt->pid;
|
||||
client.uid = pt->uid;
|
||||
client.magic = pt->magic;
|
||||
client.iocs = pt->ioctl_count;
|
||||
DRM_UNLOCK();
|
||||
|
||||
*(drm_client_t *)data = client;
|
||||
return 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_client_t *)data, client, sizeof(client) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_getstats(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_stats_t stats;
|
||||
int i;
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
DRM_LOCK();
|
||||
|
||||
for (i = 0; i < dev->counters; i++) {
|
||||
if (dev->types[i] == _DRM_STAT_LOCK)
|
||||
stats.data[i].value
|
||||
= (dev->lock.hw_lock
|
||||
? dev->lock.hw_lock->lock : 0);
|
||||
else
|
||||
stats.data[i].value = atomic_read(&dev->counts[i]);
|
||||
stats.data[i].type = dev->types[i];
|
||||
}
|
||||
|
||||
stats.count = dev->counters;
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_stats_t *)data, stats, sizeof(stats) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DRM_IF_MAJOR 1
|
||||
#define DRM_IF_MINOR 2
|
||||
|
||||
int drm_setversion(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_set_version_t sv;
|
||||
drm_set_version_t retv;
|
||||
int if_version;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
|
||||
|
||||
retv.drm_di_major = DRM_IF_MAJOR;
|
||||
retv.drm_di_minor = DRM_IF_MINOR;
|
||||
retv.drm_dd_major = dev->driver.major;
|
||||
retv.drm_dd_minor = dev->driver.minor;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
|
||||
|
||||
if (sv.drm_di_major != -1) {
|
||||
if (sv.drm_di_major != DRM_IF_MAJOR ||
|
||||
sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
|
||||
return EINVAL;
|
||||
if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
|
||||
dev->if_version = DRM_MAX(if_version, dev->if_version);
|
||||
if (sv.drm_di_minor >= 1) {
|
||||
/*
|
||||
* Version 1.1 includes tying of DRM to specific device
|
||||
*/
|
||||
drm_set_busid(dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (sv.drm_dd_major != -1) {
|
||||
if (sv.drm_dd_major != dev->driver.major ||
|
||||
sv.drm_dd_minor < 0 || sv.drm_dd_minor > dev->driver.minor)
|
||||
return EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int drm_noop(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,314 @@
|
|||
/* drm_irq.c -- IRQ IOCTL and function support
|
||||
* Created: Fri Oct 18 2003 by anholt@FreeBSD.org
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2003 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* ERIC ANHOLT 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:
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_irq.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
||||
int drm_irq_by_busid(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_irq_busid_t irq;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq));
|
||||
|
||||
if ((irq.busnum >> 8) != dev->pci_domain ||
|
||||
(irq.busnum & 0xff) != dev->pci_bus ||
|
||||
irq.devnum != dev->pci_slot ||
|
||||
irq.funcnum != dev->pci_func)
|
||||
return EINVAL;
|
||||
|
||||
irq.irq = dev->irq;
|
||||
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
irq.busnum, irq.devnum, irq.funcnum, irq.irq);
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
|
||||
static irqreturn_t
|
||||
drm_irq_handler_wrap(DRM_IRQ_ARGS)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *)arg;
|
||||
|
||||
DRM_SPINLOCK(&dev->irq_lock);
|
||||
dev->driver.irq_handler(arg);
|
||||
DRM_SPINUNLOCK(&dev->irq_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
static irqreturn_t
|
||||
drm_irq_handler_wrap(DRM_IRQ_ARGS)
|
||||
{
|
||||
int s;
|
||||
irqreturn_t ret;
|
||||
drm_device_t *dev = (drm_device_t *)arg;
|
||||
|
||||
s = spldrm();
|
||||
DRM_SPINLOCK(&dev->irq_lock);
|
||||
ret = dev->driver.irq_handler(arg);
|
||||
DRM_SPINUNLOCK(&dev->irq_lock);
|
||||
splx(s);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int drm_irq_install(drm_device_t *dev)
|
||||
{
|
||||
int retcode;
|
||||
#ifdef __NetBSD__
|
||||
pci_intr_handle_t ih;
|
||||
#endif
|
||||
|
||||
if (dev->irq == 0 || dev->dev_private == NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->irq_enabled) {
|
||||
DRM_UNLOCK();
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
dev->irq_enabled = 1;
|
||||
|
||||
dev->context_flag = 0;
|
||||
|
||||
DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
|
||||
|
||||
/* Before installing handler */
|
||||
dev->driver.irq_preinstall(dev);
|
||||
DRM_UNLOCK();
|
||||
|
||||
/* Install handler */
|
||||
#ifdef __FreeBSD__
|
||||
dev->irqrid = 0;
|
||||
dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ,
|
||||
&dev->irqrid, RF_SHAREABLE);
|
||||
if (!dev->irqr) {
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
#if __FreeBSD_version < 500000
|
||||
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY,
|
||||
dev->irq_handler, dev, &dev->irqh);
|
||||
#else
|
||||
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
|
||||
drm_irq_handler_wrap, dev, &dev->irqh);
|
||||
#endif
|
||||
if (retcode != 0)
|
||||
goto err;
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
if (pci_intr_map(&dev->pa, &ih) != 0) {
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
dev->irqh = pci_intr_establish(&dev->pa.pa_pc, ih, IPL_TTY,
|
||||
drm_irq_handler_wrap, dev);
|
||||
if (!dev->irqh) {
|
||||
retcode = ENOENT;
|
||||
goto err;
|
||||
}
|
||||
printf("dri irq ok\n");
|
||||
#endif
|
||||
|
||||
/* After installing handler */
|
||||
DRM_LOCK();
|
||||
dev->driver.irq_postinstall(dev);
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
err:
|
||||
DRM_LOCK();
|
||||
dev->irq_enabled = 0;
|
||||
#ifdef ___FreeBSD__
|
||||
if (dev->irqrid != 0) {
|
||||
bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
|
||||
dev->irqr);
|
||||
dev->irqrid = 0;
|
||||
}
|
||||
#endif
|
||||
DRM_SPINUNINIT(dev->irq_lock);
|
||||
DRM_UNLOCK();
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_irq_uninstall(drm_device_t *dev)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
int irqrid;
|
||||
#endif
|
||||
|
||||
if (!dev->irq_enabled)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
dev->irq_enabled = 0;
|
||||
#ifdef __FreeBSD__
|
||||
irqrid = dev->irqrid;
|
||||
dev->irqrid = 0;
|
||||
#endif
|
||||
|
||||
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
|
||||
|
||||
dev->driver.irq_uninstall(dev);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
DRM_UNLOCK();
|
||||
bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
|
||||
bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr);
|
||||
DRM_LOCK();
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
|
||||
#endif
|
||||
DRM_SPINUNINIT(dev->irq_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_control(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_control_t ctl;
|
||||
int err;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
|
||||
|
||||
switch ( ctl.func ) {
|
||||
case DRM_INST_HANDLER:
|
||||
/* Handle drivers whose DRM used to require IRQ setup but the
|
||||
* no longer does.
|
||||
*/
|
||||
if (!dev->driver.use_irq)
|
||||
return 0;
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl.irq != dev->irq)
|
||||
return DRM_ERR(EINVAL);
|
||||
return drm_irq_install(dev);
|
||||
case DRM_UNINST_HANDLER:
|
||||
if (!dev->driver.use_irq)
|
||||
return 0;
|
||||
DRM_LOCK();
|
||||
err = drm_irq_uninstall(dev);
|
||||
DRM_UNLOCK();
|
||||
return err;
|
||||
default:
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
int drm_wait_vblank(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_wait_vblank_t vblwait;
|
||||
struct timeval now;
|
||||
int ret;
|
||||
|
||||
if (!dev->irq_enabled)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
|
||||
sizeof(vblwait) );
|
||||
|
||||
if (vblwait.request.type & _DRM_VBLANK_RELATIVE) {
|
||||
vblwait.request.sequence += atomic_read(&dev->vbl_received);
|
||||
vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
|
||||
}
|
||||
|
||||
flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
|
||||
if (flags & _DRM_VBLANK_SIGNAL) {
|
||||
#if 0 /* disabled */
|
||||
drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (vbl_sig == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
vbl_sig->sequence = vblwait.request.sequence;
|
||||
vbl_sig->signo = vblwait.request.signal;
|
||||
vbl_sig->pid = DRM_CURRENTPID;
|
||||
|
||||
vblwait.reply.sequence = atomic_read(&dev->vbl_received);
|
||||
|
||||
DRM_SPINLOCK(&dev->irq_lock);
|
||||
TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
|
||||
DRM_SPINUNLOCK(&dev->irq_lock);
|
||||
ret = 0;
|
||||
#endif
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
DRM_LOCK();
|
||||
ret = dev->driver.vblank_wait(dev, &vblwait.request.sequence);
|
||||
DRM_UNLOCK();
|
||||
|
||||
microtime(&now);
|
||||
vblwait.reply.tval_sec = now.tv_sec;
|
||||
vblwait.reply.tval_usec = now.tv_usec;
|
||||
}
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
|
||||
sizeof(vblwait) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void drm_vbl_send_signals(drm_device_t *dev)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0 /* disabled */
|
||||
void drm_vbl_send_signals( drm_device_t *dev )
|
||||
{
|
||||
drm_vbl_sig_t *vbl_sig;
|
||||
unsigned int vbl_seq = atomic_read( &dev->vbl_received );
|
||||
struct proc *p;
|
||||
|
||||
vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
|
||||
while (vbl_sig != NULL) {
|
||||
drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
|
||||
|
||||
if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
|
||||
p = pfind(vbl_sig->pid);
|
||||
if (p != NULL)
|
||||
psignal(p, vbl_sig->signo);
|
||||
|
||||
TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link);
|
||||
DRM_FREE(vbl_sig,sizeof(*vbl_sig));
|
||||
}
|
||||
vbl_sig = next;
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,76 @@
|
|||
/* drm_linux_list.h -- linux list functions for the BSDs.
|
||||
* Created: Mon Apr 7 14:30:16 1999 by anholt@FreeBSD.org
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2003 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_linux_list.h,v 1.4 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
/* Cheat, assume the list_head is at the start of the struct */
|
||||
#define list_entry(entry, type, member) (type *)(entry)
|
||||
|
||||
static __inline__ void
|
||||
INIT_LIST_HEAD(struct list_head *head) {
|
||||
(head)->next = head;
|
||||
(head)->prev = head;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
list_empty(struct list_head *head) {
|
||||
return (head)->next == head;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
list_add_tail(struct list_head *entry, struct list_head *head) {
|
||||
(entry)->prev = (head)->prev;
|
||||
(entry)->next = head;
|
||||
(head)->prev->next = entry;
|
||||
(head)->prev = entry;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
list_del(struct list_head *entry) {
|
||||
(entry)->next->prev = (entry)->prev;
|
||||
(entry)->prev->next = (entry)->next;
|
||||
}
|
||||
|
||||
#define list_for_each(entry, head) \
|
||||
for (entry = (head)->next; entry != head; entry = (entry)->next)
|
||||
|
||||
#define list_for_each_safe(entry, temp, head) \
|
||||
for (entry = (head)->next, temp = (entry)->next; \
|
||||
temp != head; \
|
||||
entry = temp, temp = temp->next)
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/* lock.c -- IOCTLs for locking -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_lock.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new;
|
||||
|
||||
do {
|
||||
old = *lock;
|
||||
if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
|
||||
else new = context | _DRM_LOCK_HELD;
|
||||
} while (!atomic_cmpset_int(lock, old, new));
|
||||
|
||||
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
||||
if (old & _DRM_LOCK_HELD) {
|
||||
if (context != DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("%d holds heavyweight lock\n",
|
||||
context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (new == (context | _DRM_LOCK_HELD)) {
|
||||
/* Have lock */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This takes a lock forcibly and hands it to context. Should ONLY be used
|
||||
inside *_unlock to give lock to kernel before calling *_dma_schedule. */
|
||||
int drm_lock_transfer(drm_device_t *dev,
|
||||
__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new;
|
||||
|
||||
dev->lock.filp = NULL;
|
||||
do {
|
||||
old = *lock;
|
||||
new = context | _DRM_LOCK_HELD;
|
||||
} while (!atomic_cmpset_int(lock, old, new));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int drm_lock_free(drm_device_t *dev,
|
||||
__volatile__ unsigned int *lock, unsigned int context)
|
||||
{
|
||||
unsigned int old, new;
|
||||
|
||||
dev->lock.filp = NULL;
|
||||
do {
|
||||
old = *lock;
|
||||
new = 0;
|
||||
} while (!atomic_cmpset_int(lock, old, new));
|
||||
|
||||
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
|
||||
DRM_ERROR("%d freed heavyweight lock held by %d\n",
|
||||
context, _DRM_LOCKING_CONTEXT(old));
|
||||
return 1;
|
||||
}
|
||||
DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_lock(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_lock_t lock;
|
||||
int ret = 0;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock));
|
||||
|
||||
if (lock.context == DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Process %d using kernel context %d\n",
|
||||
DRM_CURRENTPID, lock.context);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
|
||||
lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock, lock.flags);
|
||||
|
||||
if (dev->driver.use_dma_queue && lock.context < 0)
|
||||
return EINVAL;
|
||||
|
||||
DRM_LOCK();
|
||||
for (;;) {
|
||||
if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) {
|
||||
dev->lock.filp = (void *)(uintptr_t)DRM_CURRENTPID;
|
||||
dev->lock.lock_time = jiffies;
|
||||
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
|
||||
break; /* Got lock */
|
||||
}
|
||||
|
||||
/* Contention */
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
|
||||
ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
|
||||
PZERO | PCATCH, "drmlk2", 0);
|
||||
#else
|
||||
ret = ltsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH,
|
||||
"drmlk2", 0, &dev->dev_lock);
|
||||
#endif
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* XXX: Add signal blocking here */
|
||||
|
||||
if (dev->driver.dma_quiescent != NULL &&
|
||||
(lock.flags & _DRM_LOCK_QUIESCENT))
|
||||
dev->driver.dma_quiescent(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_unlock(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_lock_t lock;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock));
|
||||
|
||||
if (lock.context == DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Process %d using kernel context %d\n",
|
||||
DRM_CURRENTPID, lock.context);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
|
||||
|
||||
DRM_LOCK();
|
||||
drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
|
||||
|
||||
if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) {
|
||||
DRM_ERROR("\n");
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
|
||||
* Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
|
||||
*/
|
||||
/*-
|
||||
*Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_memory.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
MALLOC_DEFINE(M_DRM, "drm", "DRM Data Structures");
|
||||
|
||||
void drm_mem_init(void)
|
||||
{
|
||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
/*
|
||||
malloc_type_attach(M_DRM);
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void drm_mem_uninit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *drm_alloc(size_t size, int area)
|
||||
{
|
||||
return malloc(size, M_DRM, M_NOWAIT);
|
||||
}
|
||||
|
||||
void *drm_calloc(size_t nmemb, size_t size, int area)
|
||||
{
|
||||
return malloc(size * nmemb, M_DRM, M_NOWAIT | M_ZERO);
|
||||
}
|
||||
|
||||
void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
|
||||
{
|
||||
void *pt;
|
||||
|
||||
pt = malloc(size, M_DRM, M_NOWAIT);
|
||||
if (pt == NULL)
|
||||
return NULL;
|
||||
if (oldpt && oldsize) {
|
||||
memcpy(pt, oldpt, oldsize);
|
||||
free(oldpt, M_DRM);
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
|
||||
void drm_free(void *pt, size_t size, int area)
|
||||
{
|
||||
free(pt, M_DRM);
|
||||
}
|
||||
|
||||
void *drm_ioremap(drm_device_t *dev, drm_local_map_t *map)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
return pmap_mapdev(map->offset, map->size);
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
int i, reg, reason;
|
||||
for(i = 0; i<DRM_MAX_PCI_RESOURCE; i++) {
|
||||
reg = PCI_MAPREG_START + i*4;
|
||||
if (dev->pci_map_data[i].maptype == PCI_MAPREG_TYPE_MEM &&
|
||||
dev->pci_map_data[i].base == map->offset &&
|
||||
dev->pci_map_data[i].size >= map->size)
|
||||
{
|
||||
map->bst = dev->pa.pa_memt;
|
||||
map->cnt = &(dev->pci_map_data[i].mapped);
|
||||
map->mapsize = dev->pci_map_data[i].size;
|
||||
dev->pci_map_data[i].mapped++;
|
||||
if (dev->pci_map_data[i].mapped > 1)
|
||||
{
|
||||
map->bsh = dev->pci_map_data[i].bsh;
|
||||
return dev->pci_map_data[i].vaddr;
|
||||
}
|
||||
if ((reason = bus_space_map(map->bst, map->offset,
|
||||
dev->pci_map_data[i].size,
|
||||
dev->pci_map_data[i].flags, &map->bsh)))
|
||||
{
|
||||
dev->pci_map_data[i].mapped--;
|
||||
DRM_DEBUG("ioremap: failed to map (%d)\n",
|
||||
reason);
|
||||
return NULL;
|
||||
}
|
||||
dev->pci_map_data[i].bsh = map->bsh;
|
||||
dev->pci_map_data[i].vaddr =
|
||||
bus_space_vaddr(map->bst, map->bsh);
|
||||
DRM_DEBUG("ioremap mem found: %p\n",
|
||||
dev->pci_map_data[i].vaddr);
|
||||
return dev->pci_map_data[i].vaddr;
|
||||
}
|
||||
}
|
||||
DRM_DEBUG("drm_ioremap failed: offset=%lx size=%lu\n",
|
||||
map->offset, map->size);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void drm_ioremapfree(drm_local_map_t *map)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
pmap_unmapdev((vm_offset_t) map->handle, map->size);
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
if (map->cnt == NULL) {
|
||||
DRM_INFO("drm_ioremapfree called for unknown map\n");
|
||||
return;
|
||||
}
|
||||
if (*(map->cnt) > 0) {
|
||||
(*(map->cnt))--;
|
||||
if(*(map->cnt) == 0)
|
||||
bus_space_unmap(map->bst, map->bsh, map->mapsize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int
|
||||
drm_mtrr_add(unsigned long offset, size_t size, int flags)
|
||||
{
|
||||
int act;
|
||||
struct mem_range_desc mrdesc;
|
||||
|
||||
mrdesc.mr_base = offset;
|
||||
mrdesc.mr_len = size;
|
||||
mrdesc.mr_flags = flags;
|
||||
act = MEMRANGE_SET_UPDATE;
|
||||
strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
|
||||
return mem_range_attr_set(&mrdesc, &act);
|
||||
}
|
||||
|
||||
int
|
||||
drm_mtrr_del(int __unused handle, unsigned long offset, size_t size, int flags)
|
||||
{
|
||||
int act;
|
||||
struct mem_range_desc mrdesc;
|
||||
|
||||
mrdesc.mr_base = offset;
|
||||
mrdesc.mr_len = size;
|
||||
mrdesc.mr_flags = flags;
|
||||
act = MEMRANGE_SET_REMOVE;
|
||||
strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
|
||||
return mem_range_attr_set(&mrdesc, &act);
|
||||
}
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
int
|
||||
drm_mtrr_add(unsigned long offset, size_t size, int flags)
|
||||
{
|
||||
struct mtrr mtrrmap;
|
||||
int one = 1;
|
||||
|
||||
DRM_DEBUG("offset=%lx size=%ld\n", (long)offset, (long)size);
|
||||
mtrrmap.base = offset;
|
||||
mtrrmap.len = size;
|
||||
mtrrmap.type = flags;
|
||||
mtrrmap.flags = MTRR_VALID;
|
||||
return mtrr_set(&mtrrmap, &one, NULL, MTRR_GETSET_KERNEL);
|
||||
}
|
||||
|
||||
int
|
||||
drm_mtrr_del(int __unused handle, unsigned long offset, size_t size, int flags)
|
||||
{
|
||||
struct mtrr mtrrmap;
|
||||
int one = 1;
|
||||
|
||||
DRM_DEBUG("offset=%lx size=%ld\n", (long)offset, (long)size);
|
||||
mtrrmap.base = offset;
|
||||
mtrrmap.len = size;
|
||||
mtrrmap.type = flags;
|
||||
mtrrmap.flags = 0;
|
||||
return mtrr_set(&mtrrmap, &one, NULL, MTRR_GETSET_KERNEL);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
* \file drm_pci.h
|
||||
* \brief PCI consistent, DMA-accessible memory functions.
|
||||
*
|
||||
* \author Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright 2003 Eric Anholt.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 THE
|
||||
* AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_pci.c,v 1.2 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/**********************************************************************/
|
||||
/** \name PCI memory */
|
||||
/*@{*/
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
static void
|
||||
drm_pci_busdma_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
{
|
||||
drm_dma_handle_t *dmah = arg;
|
||||
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
KASSERT(nsegs == 1, ("drm_pci_busdma_callback: bad dma segment count"));
|
||||
dmah->busaddr = segs[0].ds_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Allocate a physically contiguous DMA-accessible consistent
|
||||
* memory block.
|
||||
*/
|
||||
drm_dma_handle_t *
|
||||
drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr)
|
||||
{
|
||||
drm_dma_handle_t *dmah;
|
||||
int ret;
|
||||
#ifdef __NetBSD__
|
||||
int nsegs;
|
||||
#endif
|
||||
|
||||
/* Need power-of-two alignment, so fail the allocation if it isn't. */
|
||||
if ((align & (align - 1)) != 0) {
|
||||
DRM_ERROR("drm_pci_alloc with non-power-of-two alignment %d\n",
|
||||
(int)align);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dmah = malloc(sizeof(drm_dma_handle_t), M_DRM, M_ZERO | M_NOWAIT);
|
||||
if (dmah == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
ret = bus_dma_tag_create(NULL, align, 0, /* tag, align, boundary */
|
||||
maxaddr, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
|
||||
NULL, NULL, /* filtfunc, filtfuncargs */
|
||||
size, 1, size, /* maxsize, nsegs, maxsegsize */
|
||||
BUS_DMA_ALLOCNOW, NULL, NULL, /* flags, lockfunc, lockfuncargs */
|
||||
&dmah->tag);
|
||||
if (ret != 0) {
|
||||
free(dmah, M_DRM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr, BUS_DMA_NOWAIT,
|
||||
&dmah->map);
|
||||
if (ret != 0) {
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, M_DRM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr, size,
|
||||
drm_pci_busdma_callback, dmah, 0);
|
||||
if (ret != 0) {
|
||||
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, M_DRM);
|
||||
return NULL;
|
||||
}
|
||||
#elif defined(__NetBSD__)
|
||||
ret = bus_dmamem_alloc(dev->pa.pa_dmat, size, align, PAGE_SIZE,
|
||||
&dmah->seg, 1, &nsegs, BUS_DMA_NOWAIT);
|
||||
if (ret != 0) {
|
||||
free(dmah, M_DRM);
|
||||
return NULL;
|
||||
}
|
||||
if(nsegs != 1) {
|
||||
bus_dmamem_free(dev->pa.pa_dmat, &dmah->seg, nsegs);
|
||||
free(dmah, M_DRM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = bus_dmamem_map(dev->pa.pa_dmat, &dmah->seg, 1, size, &dmah->addr,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (ret != 0) {
|
||||
bus_dmamem_free(dev->pa.pa_dmat, &dmah->seg, 1);
|
||||
free(dmah, M_DRM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dmah->busaddr = dmah->seg.ds_addr;
|
||||
dmah->vaddr = dmah->addr;
|
||||
#endif
|
||||
|
||||
return dmah;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Free a DMA-accessible consistent memory block.
|
||||
*/
|
||||
void
|
||||
drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah)
|
||||
{
|
||||
if (dmah == NULL)
|
||||
return;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
#elif defined(__NetBSD__)
|
||||
bus_dmamem_free(dev->pa.pa_dmat, &dmah->seg, 1);
|
||||
#endif
|
||||
|
||||
free(dmah, M_DRM);
|
||||
}
|
||||
|
||||
/*@}*/
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* \file drm_sarea.h
|
||||
* \brief SAREA definitions
|
||||
*
|
||||
* \author Michel D<EFBFBD>zer <michel@daenzer.net>
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* TUNGSTEN GRAPHICS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_sarea.h,v 1.6 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef _DRM_SAREA_H_
|
||||
#define _DRM_SAREA_H_
|
||||
|
||||
#include "drm.h"
|
||||
|
||||
/* SAREA area needs to be at least a page */
|
||||
#if defined(__alpha__)
|
||||
#define SAREA_MAX 0x2000
|
||||
#elif defined(__ia64__)
|
||||
#define SAREA_MAX 0x10000 /* 64kB */
|
||||
#else
|
||||
/* Intel 830M driver needs at least 8k SAREA */
|
||||
#define SAREA_MAX 0x2000
|
||||
#endif
|
||||
|
||||
/** Maximum number of drawables in the SAREA */
|
||||
#define SAREA_MAX_DRAWABLES 256
|
||||
|
||||
#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000
|
||||
|
||||
/** SAREA drawable */
|
||||
typedef struct drm_sarea_drawable {
|
||||
unsigned int stamp;
|
||||
unsigned int flags;
|
||||
} drm_sarea_drawable_t;
|
||||
|
||||
/** SAREA frame */
|
||||
typedef struct drm_sarea_frame {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int fullscreen;
|
||||
} drm_sarea_frame_t;
|
||||
|
||||
/** SAREA */
|
||||
typedef struct drm_sarea {
|
||||
/** first thing is always the DRM locking structure */
|
||||
drm_hw_lock_t lock;
|
||||
/** \todo Use readers/writer lock for drm_sarea::drawable_lock */
|
||||
drm_hw_lock_t drawable_lock;
|
||||
drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; /**< drawables */
|
||||
drm_sarea_frame_t frame; /**< frame */
|
||||
drm_context_t dummy_context;
|
||||
} drm_sarea_t;
|
||||
|
||||
#endif /* _DRM_SAREA_H_ */
|
|
@ -0,0 +1,134 @@
|
|||
/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
|
||||
* Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com */
|
||||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_scatter.c,v 1.3 2006/05/17 06:29:36 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#define DEBUG_SCATTER 0
|
||||
|
||||
void drm_sg_cleanup(drm_sg_mem_t *entry)
|
||||
{
|
||||
free((void *)entry->handle, M_DRM);
|
||||
free(entry->busaddr, M_DRM);
|
||||
free(entry, M_DRM);
|
||||
}
|
||||
|
||||
int drm_sg_alloc(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_scatter_gather_t request;
|
||||
drm_sg_mem_t *entry;
|
||||
unsigned long pages;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG( "%s\n", __FUNCTION__ );
|
||||
|
||||
if ( dev->sg )
|
||||
return EINVAL;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(request, (drm_scatter_gather_t *)data,
|
||||
sizeof(request) );
|
||||
|
||||
entry = malloc(sizeof(*entry), M_DRM, M_WAITOK | M_ZERO);
|
||||
if ( !entry )
|
||||
return ENOMEM;
|
||||
|
||||
pages = round_page(request.size) / PAGE_SIZE;
|
||||
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
|
||||
|
||||
entry->pages = pages;
|
||||
|
||||
entry->busaddr = malloc(pages * sizeof(*entry->busaddr), M_DRM,
|
||||
M_WAITOK | M_ZERO);
|
||||
if ( !entry->busaddr ) {
|
||||
drm_sg_cleanup(entry);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
entry->handle = (long)malloc(pages << PAGE_SHIFT, M_DRM,
|
||||
M_WAITOK | M_ZERO);
|
||||
if (entry->handle == 0) {
|
||||
drm_sg_cleanup(entry);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < pages; i++) {
|
||||
entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE);
|
||||
}
|
||||
|
||||
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
|
||||
|
||||
entry->virtual = (void *)entry->handle;
|
||||
request.handle = entry->handle;
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL( (drm_scatter_gather_t *)data,
|
||||
request,
|
||||
sizeof(request) );
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->sg) {
|
||||
DRM_UNLOCK();
|
||||
drm_sg_cleanup(entry);
|
||||
return EINVAL;
|
||||
}
|
||||
dev->sg = entry;
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_sg_free(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_scatter_gather_t request;
|
||||
drm_sg_mem_t *entry;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( request, (drm_scatter_gather_t *)data,
|
||||
sizeof(request) );
|
||||
|
||||
DRM_LOCK();
|
||||
entry = dev->sg;
|
||||
dev->sg = NULL;
|
||||
DRM_UNLOCK();
|
||||
|
||||
if ( !entry || entry->handle != request.handle )
|
||||
return EINVAL;
|
||||
|
||||
DRM_DEBUG( "sg free virtual = 0x%lx\n", entry->handle );
|
||||
|
||||
drm_sg_cleanup(entry);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,409 @@
|
|||
/*-
|
||||
* Copyright 2003 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* ERIC ANHOLT 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_sysctl.c,v 1.2 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
static int drm_name_info DRM_SYSCTL_HANDLER_ARGS;
|
||||
static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS;
|
||||
static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS;
|
||||
static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS;
|
||||
|
||||
struct drm_sysctl_list {
|
||||
const char *name;
|
||||
int (*f) DRM_SYSCTL_HANDLER_ARGS;
|
||||
} drm_sysctl_list[] = {
|
||||
{"name", drm_name_info},
|
||||
{"vm", drm_vm_info},
|
||||
{"clients", drm_clients_info},
|
||||
{"bufs", drm_bufs_info},
|
||||
};
|
||||
#define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0]))
|
||||
|
||||
struct drm_sysctl_info {
|
||||
#ifdef __FreeBSD__
|
||||
struct sysctl_ctx_list ctx;
|
||||
#elif defined __NetBSD__
|
||||
const struct sysctlnode *dri, *dri_card, *dri_debug;
|
||||
const struct sysctlnode *dri_rest[DRM_SYSCTL_ENTRIES];
|
||||
#endif
|
||||
char name[7];
|
||||
};
|
||||
|
||||
int drm_sysctl_init(drm_device_t *dev)
|
||||
{
|
||||
struct drm_sysctl_info *info;
|
||||
#ifdef __FreeBSD__
|
||||
struct sysctl_oid *oid;
|
||||
struct sysctl_oid *top, *drioid;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
info = malloc(sizeof *info, M_DRM, M_WAITOK | M_ZERO);
|
||||
if ( !info )
|
||||
return 1;
|
||||
dev->sysctl = info;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* Add the sysctl node for DRI if it doesn't already exist */
|
||||
drioid = SYSCTL_ADD_NODE( &info->ctx, &sysctl__hw_children, OID_AUTO, "dri", CTLFLAG_RW, NULL, "DRI Graphics");
|
||||
if (!drioid)
|
||||
return 1;
|
||||
|
||||
/* Find the next free slot under hw.dri */
|
||||
i = 0;
|
||||
SLIST_FOREACH(oid, SYSCTL_CHILDREN(drioid), oid_link) {
|
||||
if (i <= oid->oid_arg2)
|
||||
i = oid->oid_arg2 + 1;
|
||||
}
|
||||
if (i>9)
|
||||
return 1;
|
||||
|
||||
/* Add the hw.dri.x for our device */
|
||||
info->name[0] = '0' + i;
|
||||
info->name[1] = 0;
|
||||
top = SYSCTL_ADD_NODE( &info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
|
||||
if (!top)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
|
||||
oid = SYSCTL_ADD_OID(&info->ctx,
|
||||
SYSCTL_CHILDREN(top),
|
||||
OID_AUTO,
|
||||
drm_sysctl_list[i].name,
|
||||
CTLTYPE_INT | CTLFLAG_RD,
|
||||
dev,
|
||||
0,
|
||||
drm_sysctl_list[i].f,
|
||||
"A",
|
||||
NULL);
|
||||
if (!oid)
|
||||
return 1;
|
||||
}
|
||||
SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(top), OID_AUTO, "debug",
|
||||
CTLFLAG_RW, &drm_debug_flag, sizeof(drm_debug_flag),
|
||||
"Enable debugging output");
|
||||
#elif defined(__NetBSD__)
|
||||
sysctl_createv(NULL, 0, NULL, &info->dri,
|
||||
CTLFLAG_READWRITE, CTLTYPE_NODE,
|
||||
"dri", SYSCTL_DESCR("DRI Graphics"), NULL, 0, NULL, 0,
|
||||
CTL_HW, CTL_CREATE);
|
||||
snprintf(info->name, 7, "card%d", dev->unit);
|
||||
sysctl_createv(NULL, 0, NULL, &info->dri_card,
|
||||
CTLFLAG_READWRITE, CTLTYPE_NODE,
|
||||
info->name, NULL, NULL, 0, NULL, 0,
|
||||
CTL_HW, info->dri->sysctl_num, CTL_CREATE);
|
||||
for (i = 0; i < DRM_SYSCTL_ENTRIES; i++)
|
||||
sysctl_createv(NULL, 0, NULL, &(info->dri_rest[i]),
|
||||
CTLFLAG_READONLY, CTLTYPE_STRING,
|
||||
drm_sysctl_list[i].name, NULL,
|
||||
drm_sysctl_list[i].f, 0, dev,
|
||||
sizeof(drm_device_t*),
|
||||
CTL_HW,
|
||||
info->dri->sysctl_num,
|
||||
info->dri_card->sysctl_num, CTL_CREATE);
|
||||
sysctl_createv(NULL, 0, NULL, &info->dri_debug,
|
||||
CTLFLAG_READWRITE, CTLTYPE_INT,
|
||||
"debug", SYSCTL_DESCR("Enable debugging output"),
|
||||
NULL, 0,
|
||||
&drm_debug_flag, sizeof(drm_debug_flag),
|
||||
CTL_HW, info->dri->sysctl_num, CTL_CREATE);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_sysctl_cleanup(drm_device_t *dev)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
int error;
|
||||
error = sysctl_ctx_free( &dev->sysctl->ctx );
|
||||
#elif defined(__NetBSD__)
|
||||
int i, error = 0;
|
||||
|
||||
sysctl_destroyv(NULL, CTL_HW, dev->sysctl->dri->sysctl_num,
|
||||
dev->sysctl->dri_debug->sysctl_num,
|
||||
CTL_DESTROY);
|
||||
for (i = 0; i < DRM_SYSCTL_ENTRIES; i++)
|
||||
sysctl_destroyv(NULL, CTL_HW, dev->sysctl->dri->sysctl_num,
|
||||
dev->sysctl->dri_card->sysctl_num,
|
||||
dev->sysctl->dri_rest[i]->sysctl_num,
|
||||
CTL_DESTROY);
|
||||
sysctl_destroyv(NULL, CTL_HW, dev->sysctl->dri->sysctl_num,
|
||||
dev->sysctl->dri_card->sysctl_num,
|
||||
CTL_DESTROY);
|
||||
sysctl_destroyv(NULL, CTL_HW, dev->sysctl->dri->sysctl_num, CTL_DESTROY);
|
||||
#endif
|
||||
|
||||
free(dev->sysctl, M_DRM);
|
||||
dev->sysctl = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#define SYSCTL_OUT(x, y, z) \
|
||||
(len+=z,(len<*oldlenp)?(strcat((char*)oldp, y),0):EOVERFLOW)
|
||||
#endif
|
||||
|
||||
#define DRM_SYSCTL_PRINT(fmt, arg...) \
|
||||
do { \
|
||||
snprintf(buf, sizeof(buf), fmt, ##arg); \
|
||||
retcode = SYSCTL_OUT(req, buf, strlen(buf)); \
|
||||
if (retcode) \
|
||||
goto done; \
|
||||
} while (0)
|
||||
|
||||
static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
drm_device_t *dev = arg1;
|
||||
#elif defined(__NetBSD__)
|
||||
int len = 0;
|
||||
drm_device_t *dev = rnode->sysctl_data;
|
||||
#endif
|
||||
char buf[128];
|
||||
int retcode;
|
||||
int hasunique = 0;
|
||||
|
||||
#ifdef __NetBSD__
|
||||
if(oldp == NULL) return EINVAL;
|
||||
*((char*)oldp) = '\0';
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
DRM_SYSCTL_PRINT("%s 0x%x", dev->driver.name, dev2udev(dev->devnode));
|
||||
#elif defined(__NetBSD__)
|
||||
DRM_SYSCTL_PRINT("%s", dev->driver.name);
|
||||
#endif
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->unique) {
|
||||
snprintf(buf, sizeof(buf), " %s", dev->unique);
|
||||
hasunique = 1;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
if (hasunique)
|
||||
SYSCTL_OUT(req, buf, strlen(buf));
|
||||
|
||||
SYSCTL_OUT(req, "", 1);
|
||||
|
||||
done:
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
drm_device_t *dev = arg1;
|
||||
#elif defined(__NetBSD__)
|
||||
int len = 0;
|
||||
drm_device_t *dev = rnode->sysctl_data;
|
||||
#endif
|
||||
drm_local_map_t *map, *tempmaps;
|
||||
const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
|
||||
const char *type, *yesno;
|
||||
int i, mapcount;
|
||||
char buf[128];
|
||||
int retcode;
|
||||
|
||||
#ifdef __NetBSD__
|
||||
if(oldp == NULL) return EINVAL;
|
||||
*((char*)oldp) = '\0';
|
||||
#endif
|
||||
|
||||
/* We can't hold the lock while doing SYSCTL_OUTs, so allocate a
|
||||
* temporary copy of all the map entries and then SYSCTL_OUT that.
|
||||
*/
|
||||
DRM_LOCK();
|
||||
|
||||
mapcount = 0;
|
||||
TAILQ_FOREACH(map, &dev->maplist, link)
|
||||
mapcount++;
|
||||
|
||||
tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, M_DRM, M_NOWAIT);
|
||||
if (tempmaps == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH(map, &dev->maplist, link)
|
||||
tempmaps[i++] = *map;
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_SYSCTL_PRINT("\nslot offset size type flags "
|
||||
"address mtrr\n");
|
||||
|
||||
for (i = 0; i < mapcount; i++) {
|
||||
map = &tempmaps[i];
|
||||
|
||||
if (/* map->type < 0 || */ map->type > 4)
|
||||
type = "??";
|
||||
else
|
||||
type = types[map->type];
|
||||
|
||||
if (!map->mtrr)
|
||||
yesno = "no";
|
||||
else
|
||||
yesno = "yes";
|
||||
|
||||
DRM_SYSCTL_PRINT(
|
||||
"%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx %s\n", i,
|
||||
map->offset, map->size, type, map->flags,
|
||||
(unsigned long)map->handle, yesno);
|
||||
}
|
||||
SYSCTL_OUT(req, "", 1);
|
||||
|
||||
done:
|
||||
free(tempmaps, M_DRM);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
drm_device_t *dev = arg1;
|
||||
#elif defined(__NetBSD__)
|
||||
int len = 0;
|
||||
drm_device_t *dev = rnode->sysctl_data;
|
||||
#endif
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_device_dma_t tempdma;
|
||||
int *templists;
|
||||
int i;
|
||||
char buf[128];
|
||||
int retcode;
|
||||
|
||||
#ifdef __NetBSD__
|
||||
if(oldp == NULL) return EINVAL;
|
||||
*((char*)oldp) = '\0';
|
||||
#endif
|
||||
|
||||
/* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
|
||||
* copy of the whole structure and the relevant data from buflist.
|
||||
*/
|
||||
DRM_LOCK();
|
||||
if (dma == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
DRM_SPINLOCK(&dev->dma_lock);
|
||||
tempdma = *dma;
|
||||
templists = malloc(sizeof(int) * dma->buf_count, M_DRM, M_NOWAIT);
|
||||
for (i = 0; i < dma->buf_count; i++)
|
||||
templists[i] = dma->buflist[i]->list;
|
||||
dma = &tempdma;
|
||||
DRM_SPINUNLOCK(&dev->dma_lock);
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n");
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
if (dma->bufs[i].buf_count)
|
||||
DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
|
||||
i,
|
||||
dma->bufs[i].buf_size,
|
||||
dma->bufs[i].buf_count,
|
||||
atomic_read(&dma->bufs[i]
|
||||
.freelist.count),
|
||||
dma->bufs[i].seg_count,
|
||||
dma->bufs[i].seg_count
|
||||
*(1 << dma->bufs[i].page_order),
|
||||
(dma->bufs[i].seg_count
|
||||
* (1 << dma->bufs[i].page_order))
|
||||
* PAGE_SIZE / 1024);
|
||||
}
|
||||
DRM_SYSCTL_PRINT("\n");
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (i && !(i%32)) DRM_SYSCTL_PRINT("\n");
|
||||
DRM_SYSCTL_PRINT(" %d", templists[i]);
|
||||
}
|
||||
DRM_SYSCTL_PRINT("\n");
|
||||
|
||||
SYSCTL_OUT(req, "", 1);
|
||||
done:
|
||||
free(templists, M_DRM);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
drm_device_t *dev = arg1;
|
||||
#elif defined(__NetBSD__)
|
||||
int len = 0;
|
||||
drm_device_t *dev = rnode->sysctl_data;
|
||||
#endif
|
||||
drm_file_t *priv, *tempprivs;
|
||||
char buf[128];
|
||||
int retcode;
|
||||
int privcount, i;
|
||||
|
||||
#ifdef __NetBSD__
|
||||
if(oldp == NULL) return EINVAL;
|
||||
*((char*)oldp) = '\0';
|
||||
#endif
|
||||
|
||||
DRM_LOCK();
|
||||
|
||||
privcount = 0;
|
||||
TAILQ_FOREACH(priv, &dev->files, link)
|
||||
privcount++;
|
||||
|
||||
tempprivs = malloc(sizeof(drm_file_t) * privcount, M_DRM, M_NOWAIT);
|
||||
if (tempprivs == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return ENOMEM;
|
||||
}
|
||||
i = 0;
|
||||
TAILQ_FOREACH(priv, &dev->files, link)
|
||||
tempprivs[i++] = *priv;
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_SYSCTL_PRINT("\na dev pid uid magic ioctls\n");
|
||||
for (i = 0; i < privcount; i++) {
|
||||
priv = &tempprivs[i];
|
||||
DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n",
|
||||
priv->authenticated ? 'y' : 'n',
|
||||
priv->minor,
|
||||
priv->pid,
|
||||
priv->uid,
|
||||
priv->magic,
|
||||
priv->ioctl_count);
|
||||
}
|
||||
|
||||
SYSCTL_OUT(req, "", 1);
|
||||
done:
|
||||
free(tempprivs, M_DRM);
|
||||
return retcode;
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*-
|
||||
* Copyright 2003 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* ERIC ANHOLT 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/drm_vm.c,v 1.2 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 500102
|
||||
int drm_mmap(struct cdev *kdev, vm_offset_t offset, vm_paddr_t *paddr,
|
||||
int prot)
|
||||
#elif defined(__FreeBSD__)
|
||||
int drm_mmap(dev_t kdev, vm_offset_t offset, int prot)
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
|
||||
#endif
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_local_map_t *map;
|
||||
drm_file_t *priv;
|
||||
drm_map_type_t type;
|
||||
#ifdef __FreeBSD__
|
||||
vm_paddr_t phys;
|
||||
#else
|
||||
paddr_t phys;
|
||||
#endif
|
||||
|
||||
DRM_LOCK();
|
||||
priv = drm_find_file_by_proc(dev, DRM_CURPROC);
|
||||
DRM_UNLOCK();
|
||||
if (priv == NULL) {
|
||||
DRM_ERROR("can't find authenticator\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (!priv->authenticated)
|
||||
return DRM_ERR(EACCES);
|
||||
|
||||
if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) {
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
|
||||
DRM_SPINLOCK(&dev->dma_lock);
|
||||
|
||||
if (dma->pagelist != NULL) {
|
||||
unsigned long page = offset >> PAGE_SHIFT;
|
||||
unsigned long pphys = dma->pagelist[page];
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 500102
|
||||
*paddr = phys;
|
||||
DRM_SPINUNLOCK(&dev->dma_lock);
|
||||
return 0;
|
||||
#else
|
||||
return atop(pphys);
|
||||
#endif
|
||||
} else {
|
||||
DRM_SPINUNLOCK(&dev->dma_lock);
|
||||
return -1;
|
||||
}
|
||||
DRM_SPINUNLOCK(&dev->dma_lock);
|
||||
}
|
||||
|
||||
/* A sequential search of a linked list is
|
||||
fine here because: 1) there will only be
|
||||
about 5-10 entries in the list and, 2) a
|
||||
DRI client only has to do this mapping
|
||||
once, so it doesn't have to be optimized
|
||||
for performance, even if the list was a
|
||||
bit longer. */
|
||||
DRM_LOCK();
|
||||
TAILQ_FOREACH(map, &dev->maplist, link) {
|
||||
if (offset >= map->offset && offset < map->offset + map->size)
|
||||
break;
|
||||
}
|
||||
|
||||
if (map == NULL) {
|
||||
DRM_UNLOCK();
|
||||
DRM_DEBUG("can't find map\n");
|
||||
return -1;
|
||||
}
|
||||
if (((map->flags&_DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) {
|
||||
DRM_UNLOCK();
|
||||
DRM_DEBUG("restricted map\n");
|
||||
return -1;
|
||||
}
|
||||
type = map->type;
|
||||
DRM_UNLOCK();
|
||||
|
||||
switch (type) {
|
||||
case _DRM_FRAME_BUFFER:
|
||||
case _DRM_REGISTERS:
|
||||
case _DRM_AGP:
|
||||
phys = offset;
|
||||
break;
|
||||
case _DRM_CONSISTENT:
|
||||
#ifdef __FreeBSD__
|
||||
phys = vtophys((char *)map->handle + (offset - map->offset));
|
||||
#else
|
||||
phys = vtophys((paddr_t)map->handle + (offset - map->offset));
|
||||
#endif
|
||||
break;
|
||||
case _DRM_SCATTER_GATHER:
|
||||
case _DRM_SHM:
|
||||
phys = vtophys(offset);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("bad map type %d\n", type);
|
||||
return -1; /* This should never happen. */
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 500102
|
||||
*paddr = phys;
|
||||
return 0;
|
||||
#else
|
||||
return atop(phys);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# $NetBSD: files.drm,v 1.1 2007/03/20 18:05:31 drochner Exp $
|
||||
|
||||
# direct rendering modules
|
||||
define drmbase
|
||||
defflag opt_drm.h DRM_DEBUG
|
||||
file dev/drm/drm_agpsupport.c drmbase
|
||||
file dev/drm/drm_auth.c drmbase
|
||||
file dev/drm/drm_bufs.c drmbase
|
||||
file dev/drm/drm_context.c drmbase
|
||||
file dev/drm/drm_dma.c drmbase
|
||||
file dev/drm/drm_drawable.c drmbase
|
||||
file dev/drm/drm_drv.c drmbase
|
||||
file dev/drm/drm_fops.c drmbase
|
||||
file dev/drm/drm_ioctl.c drmbase
|
||||
file dev/drm/drm_irq.c drmbase
|
||||
file dev/drm/drm_lock.c drmbase
|
||||
file dev/drm/drm_memory.c drmbase
|
||||
file dev/drm/drm_pci.c drmbase
|
||||
file dev/drm/drm_scatter.c drmbase
|
||||
file dev/drm/drm_sysctl.c drmbase
|
||||
file dev/drm/drm_vm.c drmbase
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: agp_i810.c,v 1.36 2007/03/04 06:02:15 christos Exp $ */
|
||||
/* $NetBSD: agp_i810.c,v 1.37 2007/03/20 18:05:31 drochner Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 Doug Rabson
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.36 2007/03/04 06:02:15 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.37 2007/03/20 18:05:31 drochner Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -155,6 +155,7 @@ agp_i810_attach(struct device *parent, struct device *self, void *aux)
|
|||
struct agp_i810_softc *isc;
|
||||
struct agp_gatt *gatt;
|
||||
int error, apbase;
|
||||
bus_size_t mmadrsize;
|
||||
|
||||
isc = malloc(sizeof *isc, M_AGP, M_NOWAIT|M_ZERO);
|
||||
if (isc == NULL) {
|
||||
|
@ -217,6 +218,9 @@ agp_i810_attach(struct device *parent, struct device *self, void *aux)
|
|||
}
|
||||
|
||||
if (isc->chiptype == CHIP_I915) {
|
||||
pci_mapreg_info(isc->vga_pa.pa_pc, isc->vga_pa.pa_tag,
|
||||
AGP_I915_MMADR, PCI_MAPREG_TYPE_MEM, NULL,
|
||||
&mmadrsize, NULL);
|
||||
error = pci_mapreg_map(&isc->vga_pa, AGP_I915_MMADR,
|
||||
PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL);
|
||||
if (error != 0) {
|
||||
|
@ -407,6 +411,12 @@ agp_i810_attach(struct device *parent, struct device *self, void *aux)
|
|||
printf("%s: WARNING: unable to establish PCI power hook\n",
|
||||
sc->as_dev.dv_xname);
|
||||
|
||||
/*
|
||||
* another device (drm) may need access to this region
|
||||
* we do not need it anymore
|
||||
*/
|
||||
bus_space_unmap(isc->bst, isc->bsh, mmadrsize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -713,6 +723,8 @@ agp_i810_bind_memory(struct agp_softc *sc, struct agp_memory *mem,
|
|||
* to the GTT through the MMIO window.
|
||||
* Until the issue is solved, simply restore it.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL);
|
||||
if (regval != (isc->gatt->ag_physical | 1)) {
|
||||
printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
|
||||
|
@ -720,6 +732,8 @@ agp_i810_bind_memory(struct agp_softc *sc, struct agp_memory *mem,
|
|||
bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL,
|
||||
isc->gatt->ag_physical | 1);
|
||||
}
|
||||
#endif
|
||||
regval = 0;
|
||||
|
||||
if (mem->am_type == 2) {
|
||||
WRITEGTT(offset, mem->am_physical | 1);
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
|
||||
* Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/ati_pcigart.c,v 1.3 2005/11/28 23:13:52 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
|
||||
#define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */
|
||||
#define ATI_PCIGART_TABLE_SIZE 32768
|
||||
|
||||
int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
unsigned long pages;
|
||||
u32 *pci_gart = NULL, page_base;
|
||||
int i, j;
|
||||
|
||||
if (dev->sg == NULL) {
|
||||
DRM_ERROR( "no scatter/gather memory!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
/* GART table in system memory */
|
||||
dev->sg->dmah = drm_pci_alloc(dev, ATI_PCIGART_TABLE_SIZE, 0,
|
||||
0xfffffffful);
|
||||
if (dev->sg->dmah == NULL) {
|
||||
DRM_ERROR("cannot allocate PCI GART table!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gart_info->addr = (void *)dev->sg->dmah->vaddr;
|
||||
gart_info->bus_addr = dev->sg->dmah->busaddr;
|
||||
pci_gart = (u32 *)dev->sg->dmah->vaddr;
|
||||
} else {
|
||||
/* GART table in framebuffer memory */
|
||||
pci_gart = gart_info->addr;
|
||||
}
|
||||
|
||||
pages = DRM_MIN(dev->sg->pages, ATI_MAX_PCIGART_PAGES);
|
||||
|
||||
bzero(pci_gart, ATI_PCIGART_TABLE_SIZE);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE, ("page size too small"));
|
||||
#elif defined(__NetBSD__)
|
||||
KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE);
|
||||
#endif
|
||||
|
||||
for ( i = 0 ; i < pages ; i++ ) {
|
||||
page_base = (u32) dev->sg->busaddr[i];
|
||||
|
||||
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
|
||||
if (gart_info->is_pcie)
|
||||
*pci_gart = (cpu_to_le32(page_base) >> 8) | 0xc;
|
||||
else
|
||||
*pci_gart = cpu_to_le32(page_base);
|
||||
pci_gart++;
|
||||
page_base += ATI_PCIGART_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_MEMORYBARRIER();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
if (dev->sg == NULL) {
|
||||
DRM_ERROR( "no scatter/gather memory!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
drm_pci_free(dev, dev->sg->dmah);
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,484 @@
|
|||
/*
|
||||
* $FreeBSD: src/sys/dev/drm/drm_pciids.h,v 1.7 2006/09/07 23:04:47 anholt Exp $
|
||||
*/
|
||||
/*
|
||||
This file is auto-generated from the drm_pciids.txt in the DRM CVS
|
||||
Please contact dri-devel@lists.sf.net to add new cards to this list
|
||||
*/
|
||||
#define radeon_PCI_IDS \
|
||||
{0x1002, 0x3150, CHIP_RV380|CHIP_IS_MOBILITY, "ATI Radeon Mobility X600 M24"}, \
|
||||
{0x1002, 0x3152, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Radeon Mobility X300 M24"}, \
|
||||
{0x1002, 0x3154, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI FireGL M24 GL"}, \
|
||||
{0x1002, 0x3E50, CHIP_RV380|CHIP_NEW_MEMMAP, "ATI Radeon RV380 X600"}, \
|
||||
{0x1002, 0x3E54, CHIP_RV380|CHIP_NEW_MEMMAP, "ATI FireGL V3200 RV380"}, \
|
||||
{0x1002, 0x4136, CHIP_RS100|CHIP_IS_IGP, "ATI Radeon RS100 IGP 320"}, \
|
||||
{0x1002, 0x4137, CHIP_RS200|CHIP_IS_IGP, "ATI Radeon RS200 IGP 340"}, \
|
||||
{0x1002, 0x4144, CHIP_R300, "ATI Radeon AD 9500"}, \
|
||||
{0x1002, 0x4145, CHIP_R300, "ATI Radeon AE 9700 Pro"}, \
|
||||
{0x1002, 0x4146, CHIP_R300, "ATI Radeon AF R300 9600TX"}, \
|
||||
{0x1002, 0x4147, CHIP_R300, "ATI FireGL AG Z1"}, \
|
||||
{0x1002, 0x4148, CHIP_R350, "ATI Radeon AH 9800 SE"}, \
|
||||
{0x1002, 0x4149, CHIP_R350, "ATI Radeon AI 9800"}, \
|
||||
{0x1002, 0x414A, CHIP_R350, "ATI Radeon AJ 9800"}, \
|
||||
{0x1002, 0x414B, CHIP_R350, "ATI FireGL AK X2"}, \
|
||||
{0x1002, 0x4150, CHIP_RV350, "ATI Radeon AP 9600"}, \
|
||||
{0x1002, 0x4151, CHIP_RV350, "ATI Radeon AQ 9600 SE"}, \
|
||||
{0x1002, 0x4152, CHIP_RV350, "ATI Radeon AR 9600 XT"}, \
|
||||
{0x1002, 0x4153, CHIP_RV350, "ATI Radeon AS 9550"}, \
|
||||
{0x1002, 0x4154, CHIP_RV350, "ATI FireGL AT T2"}, \
|
||||
{0x1002, 0x4155, CHIP_RV350, "ATI Radeon 9650"}, \
|
||||
{0x1002, 0x4156, CHIP_RV350, "ATI FireGL AV RV360 T2"}, \
|
||||
{0x1002, 0x4237, CHIP_RS200|CHIP_IS_IGP, "ATI Radeon RS250 IGP"}, \
|
||||
{0x1002, 0x4242, CHIP_R200, "ATI Radeon BB R200 AIW 8500DV"}, \
|
||||
{0x1002, 0x4243, CHIP_R200, "ATI Radeon BC R200"}, \
|
||||
{0x1002, 0x4336, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY, "ATI Radeon RS100 Mobility U1"}, \
|
||||
{0x1002, 0x4337, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY, "ATI Radeon RS200 Mobility IGP 340M"}, \
|
||||
{0x1002, 0x4437, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY, "ATI Radeon RS250 Mobility IGP"}, \
|
||||
{0x1002, 0x4966, CHIP_RV250, "ATI Radeon If RV250 9000"}, \
|
||||
{0x1002, 0x4967, CHIP_RV250, "ATI Radeon Ig RV250 9000"}, \
|
||||
{0x1002, 0x4A48, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon JH R420 X800"}, \
|
||||
{0x1002, 0x4A49, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon JI R420 X800 Pro"}, \
|
||||
{0x1002, 0x4A4A, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon JJ R420 X800 SE"}, \
|
||||
{0x1002, 0x4A4B, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon JK R420 X800 XT"}, \
|
||||
{0x1002, 0x4A4C, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon JL R420 X800"}, \
|
||||
{0x1002, 0x4A4D, CHIP_R420|CHIP_NEW_MEMMAP, "ATI FireGL JM X3-256"}, \
|
||||
{0x1002, 0x4A4E, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Radeon JN R420 Mobility M18"}, \
|
||||
{0x1002, 0x4A4F, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon JO R420 X800 SE"}, \
|
||||
{0x1002, 0x4A50, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon JP R420 X800 XT PE"}, \
|
||||
{0x1002, 0x4A54, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon JT R420 AIW X800 VE"}, \
|
||||
{0x1002, 0x4B49, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R481 X850 XT"}, \
|
||||
{0x1002, 0x4B4A, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R481 X850 SE"}, \
|
||||
{0x1002, 0x4B4B, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R481 X850 Pro"}, \
|
||||
{0x1002, 0x4B4C, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R481 X850 XT PE"}, \
|
||||
{0x1002, 0x4C57, CHIP_RV200|CHIP_IS_MOBILITY, "ATI Radeon LW RV200 Mobility 7500 M7"}, \
|
||||
{0x1002, 0x4C58, CHIP_RV200|CHIP_IS_MOBILITY, "ATI Radeon LX RV200 Mobility FireGL 7800 M7"}, \
|
||||
{0x1002, 0x4C59, CHIP_RV100|CHIP_IS_MOBILITY, "ATI Radeon LY RV100 Mobility M6"}, \
|
||||
{0x1002, 0x4C5A, CHIP_RV100|CHIP_IS_MOBILITY, "ATI Radeon LZ RV100 Mobility M6"}, \
|
||||
{0x1002, 0x4C64, CHIP_RV250|CHIP_IS_MOBILITY, "ATI Radeon Ld RV250 Mobility 9000 M9"}, \
|
||||
{0x1002, 0x4C66, CHIP_RV250, "ATI Radeon Lf RV250 Mobility 9000 M9 / FireMV 2400 PCI"}, \
|
||||
{0x1002, 0x4C67, CHIP_RV250|CHIP_IS_MOBILITY, "ATI Radeon Lg RV250 Mobility 9000 M9"}, \
|
||||
{0x1002, 0x4E44, CHIP_R300, "ATI Radeon ND R300 9700 Pro"}, \
|
||||
{0x1002, 0x4E45, CHIP_R300, "ATI Radeon NE R300 9500 Pro / 9700"}, \
|
||||
{0x1002, 0x4E46, CHIP_R300, "ATI Radeon NF R300 9600TX"}, \
|
||||
{0x1002, 0x4E47, CHIP_R300, "ATI Radeon NG R300 FireGL X1"}, \
|
||||
{0x1002, 0x4E48, CHIP_R350, "ATI Radeon NH R350 9800 Pro"}, \
|
||||
{0x1002, 0x4E49, CHIP_R350, "ATI Radeon NI R350 9800"}, \
|
||||
{0x1002, 0x4E4A, CHIP_R350, "ATI Radeon NJ R360 9800 XT"}, \
|
||||
{0x1002, 0x4E4B, CHIP_R350, "ATI FireGL NK X2"}, \
|
||||
{0x1002, 0x4E50, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon RV350 Mobility 9600 M10 NP"}, \
|
||||
{0x1002, 0x4E51, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon RV350 Mobility 9600 M10 NQ"}, \
|
||||
{0x1002, 0x4E52, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon RV350 Mobility 9600 M11 NR"}, \
|
||||
{0x1002, 0x4E53, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon RV350 Mobility 9600 M10 NS"}, \
|
||||
{0x1002, 0x4E54, CHIP_RV350|CHIP_IS_MOBILITY, "ATI FireGL T2/T2e"}, \
|
||||
{0x1002, 0x4E56, CHIP_RV350|CHIP_IS_MOBILITY, "ATI Radeon Mobility 9550"}, \
|
||||
{0x1002, 0x5144, CHIP_R100|CHIP_SINGLE_CRTC, "ATI Radeon QD R100"}, \
|
||||
{0x1002, 0x5145, CHIP_R100|CHIP_SINGLE_CRTC, "ATI Radeon QE R100"}, \
|
||||
{0x1002, 0x5146, CHIP_R100|CHIP_SINGLE_CRTC, "ATI Radeon QF R100"}, \
|
||||
{0x1002, 0x5147, CHIP_R100|CHIP_SINGLE_CRTC, "ATI Radeon QG R100"}, \
|
||||
{0x1002, 0x5148, CHIP_R200, "ATI Radeon QH R200 8500"}, \
|
||||
{0x1002, 0x514C, CHIP_R200, "ATI Radeon QL R200 8500 LE"}, \
|
||||
{0x1002, 0x514D, CHIP_R200, "ATI Radeon QM R200 9100"}, \
|
||||
{0x1002, 0x5157, CHIP_RV200, "ATI Radeon QW RV200 7500"}, \
|
||||
{0x1002, 0x5158, CHIP_RV200, "ATI Radeon QX RV200 7500"}, \
|
||||
{0x1002, 0x5159, CHIP_RV100, "ATI Radeon QY RV100 7000/VE"}, \
|
||||
{0x1002, 0x515A, CHIP_RV100, "ATI Radeon QZ RV100 7000/VE"}, \
|
||||
{0x1002, 0x515E, CHIP_RV100, "ATI ES1000 RN50"}, \
|
||||
{0x1002, 0x5460, CHIP_RV380|CHIP_IS_MOBILITY, "ATI Radeon Mobility X300 M22"}, \
|
||||
{0x1002, 0x5462, CHIP_RV380|CHIP_IS_MOBILITY, "ATI Radeon Mobility X600 SE M24C"}, \
|
||||
{0x1002, 0x5464, CHIP_RV380|CHIP_IS_MOBILITY, "ATI FireGL M22 GL 5464"}, \
|
||||
{0x1002, 0x5548, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R423 X800"}, \
|
||||
{0x1002, 0x5549, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R423 X800 Pro"}, \
|
||||
{0x1002, 0x554A, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R423 X800 XT PE"}, \
|
||||
{0x1002, 0x554B, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R423 X800 SE"}, \
|
||||
{0x1002, 0x554C, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R430 X800 XTP"}, \
|
||||
{0x1002, 0x554D, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R430 X800 XL"}, \
|
||||
{0x1002, 0x554E, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R430 X800 SE"}, \
|
||||
{0x1002, 0x554F, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R430 X800"}, \
|
||||
{0x1002, 0x5550, CHIP_R420|CHIP_NEW_MEMMAP, "ATI FireGL V7100 R423"}, \
|
||||
{0x1002, 0x5551, CHIP_R420|CHIP_NEW_MEMMAP, "ATI FireGL V5100 R423 UQ"}, \
|
||||
{0x1002, 0x5552, CHIP_R420|CHIP_NEW_MEMMAP, "ATI FireGL unknown R423 UR"}, \
|
||||
{0x1002, 0x5554, CHIP_R420|CHIP_NEW_MEMMAP, "ATI FireGL unknown R423 UT"}, \
|
||||
{0x1002, 0x564A, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Mobility FireGL V5000 M26"}, \
|
||||
{0x1002, 0x564B, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Mobility FireGL V5000 M26"}, \
|
||||
{0x1002, 0x564F, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Radeon Mobility X700 XL M26"}, \
|
||||
{0x1002, 0x5652, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Radeon Mobility X700 M26"}, \
|
||||
{0x1002, 0x5653, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Radeon Mobility X700 M26"}, \
|
||||
{0x1002, 0x5834, CHIP_RS300|CHIP_IS_IGP, "ATI Radeon RS300 9100 IGP"}, \
|
||||
{0x1002, 0x5835, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY, "ATI Radeon RS300 Mobility IGP"}, \
|
||||
{0x1002, 0x5960, CHIP_RV280, "ATI Radeon RV280 9250"}, \
|
||||
{0x1002, 0x5961, CHIP_RV280, "ATI Radeon RV280 9200"}, \
|
||||
{0x1002, 0x5962, CHIP_RV280, "ATI Radeon RV280 9200"}, \
|
||||
{0x1002, 0x5964, CHIP_RV280, "ATI Radeon RV280 9200 SE"}, \
|
||||
{0x1002, 0x5965, CHIP_RV280, "ATI FireMV 2200 PCI"}, \
|
||||
{0x1002, 0x5969, CHIP_RV100, "ATI ES1000 RN50"}, \
|
||||
{0x1002, 0x5b60, CHIP_RV380|CHIP_NEW_MEMMAP, "ATI Radeon RV370 X300 SE"}, \
|
||||
{0x1002, 0x5b62, CHIP_RV380|CHIP_NEW_MEMMAP, "ATI Radeon RV370 X600 Pro"}, \
|
||||
{0x1002, 0x5b63, CHIP_RV380|CHIP_NEW_MEMMAP, "ATI Radeon RV370 X550"}, \
|
||||
{0x1002, 0x5b64, CHIP_RV380|CHIP_NEW_MEMMAP, "ATI FireGL V3100 (RV370) 5B64"}, \
|
||||
{0x1002, 0x5b65, CHIP_RV380|CHIP_NEW_MEMMAP, "ATI FireMV 2200 PCIE (RV370) 5B65"}, \
|
||||
{0x1002, 0x5c61, CHIP_RV280|CHIP_IS_MOBILITY, "ATI Radeon RV280 Mobility"}, \
|
||||
{0x1002, 0x5c63, CHIP_RV280|CHIP_IS_MOBILITY, "ATI Radeon RV280 Mobility"}, \
|
||||
{0x1002, 0x5d48, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Mobility Radeon X800 XT M28"}, \
|
||||
{0x1002, 0x5d49, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Mobility FireGL V5100 M28"}, \
|
||||
{0x1002, 0x5d4a, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Mobility Radeon X800 M28"}, \
|
||||
{0x1002, 0x5d4c, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R480 X850"}, \
|
||||
{0x1002, 0x5d4d, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R480 X850 XT PE"}, \
|
||||
{0x1002, 0x5d4e, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R480 X850 SE"}, \
|
||||
{0x1002, 0x5d4f, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R480 X850 Pro"}, \
|
||||
{0x1002, 0x5d50, CHIP_R420|CHIP_NEW_MEMMAP, "ATI unknown Radeon / FireGL R480"}, \
|
||||
{0x1002, 0x5d52, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R480 X850 XT"}, \
|
||||
{0x1002, 0x5d57, CHIP_R420|CHIP_NEW_MEMMAP, "ATI Radeon R423 X800 XT"}, \
|
||||
{0x1002, 0x5e48, CHIP_RV410|CHIP_NEW_MEMMAP, "ATI FireGL V5000 RV410"}, \
|
||||
{0x1002, 0x5e4a, CHIP_RV410|CHIP_NEW_MEMMAP, "ATI Radeon RV410 X700 XT"}, \
|
||||
{0x1002, 0x5e4b, CHIP_RV410|CHIP_NEW_MEMMAP, "ATI Radeon RV410 X700 Pro"}, \
|
||||
{0x1002, 0x5e4c, CHIP_RV410|CHIP_NEW_MEMMAP, "ATI Radeon RV410 X700 SE"}, \
|
||||
{0x1002, 0x5e4d, CHIP_RV410|CHIP_NEW_MEMMAP, "ATI Radeon RV410 X700"}, \
|
||||
{0x1002, 0x5e4f, CHIP_RV410|CHIP_NEW_MEMMAP, "ATI Radeon RV410 X700 SE"}, \
|
||||
{0x1002, 0x7834, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP, "ATI Radeon RS350 9000/9100 IGP"}, \
|
||||
{0x1002, 0x7835, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP, "ATI Radeon RS350 Mobility IGP"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define r128_PCI_IDS \
|
||||
{0x1002, 0x4c45, 0, "ATI Rage 128 Mobility LE (PCI)"}, \
|
||||
{0x1002, 0x4c46, 0, "ATI Rage 128 Mobility LF (AGP)"}, \
|
||||
{0x1002, 0x4d46, 0, "ATI Rage 128 Mobility MF (AGP)"}, \
|
||||
{0x1002, 0x4d4c, 0, "ATI Rage 128 Mobility ML (AGP)"}, \
|
||||
{0x1002, 0x5041, 0, "ATI Rage 128 Pro PA (PCI)"}, \
|
||||
{0x1002, 0x5042, 0, "ATI Rage 128 Pro PB (AGP)"}, \
|
||||
{0x1002, 0x5043, 0, "ATI Rage 128 Pro PC (AGP)"}, \
|
||||
{0x1002, 0x5044, 0, "ATI Rage 128 Pro PD (PCI)"}, \
|
||||
{0x1002, 0x5045, 0, "ATI Rage 128 Pro PE (AGP)"}, \
|
||||
{0x1002, 0x5046, 0, "ATI Rage 128 Pro PF (AGP)"}, \
|
||||
{0x1002, 0x5047, 0, "ATI Rage 128 Pro PG (PCI)"}, \
|
||||
{0x1002, 0x5048, 0, "ATI Rage 128 Pro PH (AGP)"}, \
|
||||
{0x1002, 0x5049, 0, "ATI Rage 128 Pro PI (AGP)"}, \
|
||||
{0x1002, 0x504A, 0, "ATI Rage 128 Pro PJ (PCI)"}, \
|
||||
{0x1002, 0x504B, 0, "ATI Rage 128 Pro PK (AGP)"}, \
|
||||
{0x1002, 0x504C, 0, "ATI Rage 128 Pro PL (AGP)"}, \
|
||||
{0x1002, 0x504D, 0, "ATI Rage 128 Pro PM (PCI)"}, \
|
||||
{0x1002, 0x504E, 0, "ATI Rage 128 Pro PN (AGP)"}, \
|
||||
{0x1002, 0x504F, 0, "ATI Rage 128 Pro PO (AGP)"}, \
|
||||
{0x1002, 0x5050, 0, "ATI Rage 128 Pro PP (PCI)"}, \
|
||||
{0x1002, 0x5051, 0, "ATI Rage 128 Pro PQ (AGP)"}, \
|
||||
{0x1002, 0x5052, 0, "ATI Rage 128 Pro PR (PCI)"}, \
|
||||
{0x1002, 0x5053, 0, "ATI Rage 128 Pro PS (PCI)"}, \
|
||||
{0x1002, 0x5054, 0, "ATI Rage 128 Pro PT (AGP)"}, \
|
||||
{0x1002, 0x5055, 0, "ATI Rage 128 Pro PU (AGP)"}, \
|
||||
{0x1002, 0x5056, 0, "ATI Rage 128 Pro PV (PCI)"}, \
|
||||
{0x1002, 0x5057, 0, "ATI Rage 128 Pro PW (AGP)"}, \
|
||||
{0x1002, 0x5058, 0, "ATI Rage 128 Pro PX (AGP)"}, \
|
||||
{0x1002, 0x5245, 0, "ATI Rage 128 RE (PCI)"}, \
|
||||
{0x1002, 0x5246, 0, "ATI Rage 128 RF (AGP)"}, \
|
||||
{0x1002, 0x5247, 0, "ATI Rage 128 RG (AGP)"}, \
|
||||
{0x1002, 0x524b, 0, "ATI Rage 128 RK (PCI)"}, \
|
||||
{0x1002, 0x524c, 0, "ATI Rage 128 RL (AGP)"}, \
|
||||
{0x1002, 0x534d, 0, "ATI Rage 128 SM (AGP)"}, \
|
||||
{0x1002, 0x5446, 0, "ATI Rage 128 Pro Ultra TF (AGP)"}, \
|
||||
{0x1002, 0x544C, 0, "ATI Rage 128 Pro Ultra TL (AGP)"}, \
|
||||
{0x1002, 0x5452, 0, "ATI Rage 128 Pro Ultra TR (AGP)"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define mga_PCI_IDS \
|
||||
{0x102b, 0x0520, MGA_CARD_TYPE_G200, "Matrox G200 (PCI)"}, \
|
||||
{0x102b, 0x0521, MGA_CARD_TYPE_G200, "Matrox G200 (AGP)"}, \
|
||||
{0x102b, 0x0525, MGA_CARD_TYPE_G400, "Matrox G400/G450 (AGP)"}, \
|
||||
{0x102b, 0x2527, MGA_CARD_TYPE_G550, "Matrox G550 (AGP)"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define mach64_PCI_IDS \
|
||||
{0x1002, 0x4749, 0, "3D Rage Pro"}, \
|
||||
{0x1002, 0x4750, 0, "3D Rage Pro 215GP"}, \
|
||||
{0x1002, 0x4751, 0, "3D Rage Pro 215GQ"}, \
|
||||
{0x1002, 0x4742, 0, "3D Rage Pro AGP 1X/2X"}, \
|
||||
{0x1002, 0x4744, 0, "3D Rage Pro AGP 1X"}, \
|
||||
{0x1002, 0x4c49, 0, "3D Rage LT Pro"}, \
|
||||
{0x1002, 0x4c50, 0, "3D Rage LT Pro"}, \
|
||||
{0x1002, 0x4c51, 0, "3D Rage LT Pro"}, \
|
||||
{0x1002, 0x4c42, 0, "3D Rage LT Pro AGP-133"}, \
|
||||
{0x1002, 0x4c44, 0, "3D Rage LT Pro AGP-66"}, \
|
||||
{0x1002, 0x474c, 0, "Rage XC"}, \
|
||||
{0x1002, 0x474f, 0, "Rage XL"}, \
|
||||
{0x1002, 0x4752, 0, "Rage XL"}, \
|
||||
{0x1002, 0x4753, 0, "Rage XC"}, \
|
||||
{0x1002, 0x474d, 0, "Rage XL AGP 2X"}, \
|
||||
{0x1002, 0x474e, 0, "Rage XC AGP"}, \
|
||||
{0x1002, 0x4c52, 0, "Rage Mobility P/M"}, \
|
||||
{0x1002, 0x4c53, 0, "Rage Mobility L"}, \
|
||||
{0x1002, 0x4c4d, 0, "Rage Mobility P/M AGP 2X"}, \
|
||||
{0x1002, 0x4c4e, 0, "Rage Mobility L AGP 2X"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define sis_PCI_IDS \
|
||||
{0x1039, 0x0300, 0, "SiS 300/305"}, \
|
||||
{0x1039, 0x5300, 0, "SiS 540"}, \
|
||||
{0x1039, 0x6300, 0, "SiS 630"}, \
|
||||
{0x1039, 0x7300, 0, "SiS 730"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define tdfx_PCI_IDS \
|
||||
{0x121a, 0x0003, 0, "3dfx Voodoo Banshee"}, \
|
||||
{0x121a, 0x0004, 0, "3dfx Voodoo3 2000"}, \
|
||||
{0x121a, 0x0005, 0, "3dfx Voodoo3 3000"}, \
|
||||
{0x121a, 0x0007, 0, "3dfx Voodoo4 4500"}, \
|
||||
{0x121a, 0x0009, 0, "3dfx Voodoo5 5500"}, \
|
||||
{0x121a, 0x000b, 0, "3dfx Voodoo4 4200"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define viadrv_PCI_IDS \
|
||||
{0x1106, 0x3022, 0, "VIA CLE266 3022"}, \
|
||||
{0x1106, 0x3118, VIA_PRO_GROUP_A, "VIA CN400 / PM8X0"}, \
|
||||
{0x1106, 0x3122, 0, "VIA CLE266"}, \
|
||||
{0x1106, 0x7205, 0, "VIA KM400"}, \
|
||||
{0x1106, 0x3108, 0, "VIA K8M800"}, \
|
||||
{0x1106, 0x3344, 0, "VIA P4VM800PRO"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define i810_PCI_IDS \
|
||||
{0x8086, 0x7121, 0, "Intel i810 GMCH"}, \
|
||||
{0x8086, 0x7123, 0, "Intel i810-DC100 GMCH"}, \
|
||||
{0x8086, 0x7125, 0, "Intel i810E GMCH"}, \
|
||||
{0x8086, 0x1132, 0, "Intel i815 GMCH"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define i830_PCI_IDS \
|
||||
{0x8086, 0x3577, 0, "Intel i830M GMCH"}, \
|
||||
{0x8086, 0x2562, 0, "Intel i845G GMCH"}, \
|
||||
{0x8086, 0x3582, 0, "Intel i852GM/i855GM GMCH"}, \
|
||||
{0x8086, 0x2572, 0, "Intel i865G GMCH"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define gamma_PCI_IDS \
|
||||
{0x3d3d, 0x0008, 0, "3DLabs GLINT Gamma G1"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define savage_PCI_IDS \
|
||||
{0x5333, 0x8a20, S3_SAVAGE3D, "Savage 3D"}, \
|
||||
{0x5333, 0x8a21, S3_SAVAGE3D, "Savage 3D/MV"}, \
|
||||
{0x5333, 0x8a22, S3_SAVAGE4, "Savage4"}, \
|
||||
{0x5333, 0x8a23, S3_SAVAGE4, "Savage4"}, \
|
||||
{0x5333, 0x8c10, S3_SAVAGE_MX, "Savage/MX-MV"}, \
|
||||
{0x5333, 0x8c11, S3_SAVAGE_MX, "Savage/MX"}, \
|
||||
{0x5333, 0x8c12, S3_SAVAGE_MX, "Savage/IX-MV"}, \
|
||||
{0x5333, 0x8c13, S3_SAVAGE_MX, "Savage/IX"}, \
|
||||
{0x5333, 0x8c22, S3_SUPERSAVAGE, "SuperSavage MX/128"}, \
|
||||
{0x5333, 0x8c24, S3_SUPERSAVAGE, "SuperSavage MX/64"}, \
|
||||
{0x5333, 0x8c26, S3_SUPERSAVAGE, "SuperSavage MX/64C"}, \
|
||||
{0x5333, 0x8c2a, S3_SUPERSAVAGE, "SuperSavage IX/128 SDR"}, \
|
||||
{0x5333, 0x8c2b, S3_SUPERSAVAGE, "SuperSavage IX/128 DDR"}, \
|
||||
{0x5333, 0x8c2c, S3_SUPERSAVAGE, "SuperSavage IX/64 SDR"}, \
|
||||
{0x5333, 0x8c2d, S3_SUPERSAVAGE, "SuperSavage IX/64 DDR"}, \
|
||||
{0x5333, 0x8c2e, S3_SUPERSAVAGE, "SuperSavage IX/C SDR"}, \
|
||||
{0x5333, 0x8c2f, S3_SUPERSAVAGE, "SuperSavage IX/C DDR"}, \
|
||||
{0x5333, 0x8a25, S3_PROSAVAGE, "ProSavage PM133"}, \
|
||||
{0x5333, 0x8a26, S3_PROSAVAGE, "ProSavage KM133"}, \
|
||||
{0x5333, 0x8d01, S3_TWISTER, "ProSavage Twister PN133"}, \
|
||||
{0x5333, 0x8d02, S3_TWISTER, "ProSavage Twister KN133"}, \
|
||||
{0x5333, 0x8d03, S3_PROSAVAGEDDR, "ProSavage DDR"}, \
|
||||
{0x5333, 0x8d04, S3_PROSAVAGEDDR, "ProSavage DDR-K"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define ffb_PCI_IDS \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define i915_PCI_IDS \
|
||||
{0x8086, 0x3577, 0, "Intel i830M GMCH"}, \
|
||||
{0x8086, 0x2562, 0, "Intel i845G GMCH"}, \
|
||||
{0x8086, 0x3582, 0, "Intel i852GM/i855GM GMCH"}, \
|
||||
{0x8086, 0x2572, 0, "Intel i865G GMCH"}, \
|
||||
{0x8086, 0x2582, 0, "Intel i915G"}, \
|
||||
{0x8086, 0x2592, 0, "Intel i915GM"}, \
|
||||
{0x8086, 0x2772, 0, "Intel i945G"}, \
|
||||
{0x8086, 0x27A2, 0, "Intel i945GM"}, \
|
||||
{0x8086, 0x2972, 0, "Intel i946GZ"}, \
|
||||
{0x8086, 0x2982, 0, "Intel i965G"}, \
|
||||
{0x8086, 0x2992, 0, "Intel i965Q"}, \
|
||||
{0x8086, 0x29A2, 0, "Intel i965G"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define imagine_PCI_IDS \
|
||||
{0x105d, 0x2309, IMAGINE_128, "Imagine 128"}, \
|
||||
{0x105d, 0x2339, IMAGINE_128_2, "Imagine 128-II"}, \
|
||||
{0x105d, 0x493d, IMAGINE_T2R, "Ticket to Ride"}, \
|
||||
{0x105d, 0x5348, IMAGINE_REV4, "Revolution IV"}, \
|
||||
{0, 0, 0, NULL}
|
||||
|
||||
#define nv_PCI_IDS \
|
||||
{0x10DE, 0x0020, NV04, "NVidia RIVA TNT"}, \
|
||||
{0x10DE, 0x0028, NV04, "NVidia RIVA TNT2"}, \
|
||||
{0x10DE, 0x002A, NV04, "NVidia Unknown TNT2"}, \
|
||||
{0x10DE, 0x002C, NV04, "NVidia Vanta"}, \
|
||||
{0x10DE, 0x0029, NV04, "NVidia RIVA TNT2 Ultra"}, \
|
||||
{0x10DE, 0x002D, NV04, "NVidia RIVA TNT2 Model 64"}, \
|
||||
{0x10DE, 0x00A0, NV04, "NVidia Aladdin TNT2"}, \
|
||||
{0x10DE, 0x0100, NV10, "NVidia GeForce 256"}, \
|
||||
{0x10DE, 0x0101, NV10, "NVidia GeForce DDR"}, \
|
||||
{0x10DE, 0x0103, NV10, "NVidia Quadro"}, \
|
||||
{0x10DE, 0x0110, NV10, "NVidia GeForce2 MX/MX 400"}, \
|
||||
{0x10DE, 0x0111, NV10, "NVidia GeForce2 MX 100/200"}, \
|
||||
{0x10DE, 0x0112, NV10, "NVidia GeForce2 Go"}, \
|
||||
{0x10DE, 0x0113, NV10, "NVidia Quadro2 MXR/EX/Go"}, \
|
||||
{0x10DE, 0x0150, NV10, "NVidia GeForce2 GTS"}, \
|
||||
{0x10DE, 0x0151, NV10, "NVidia GeForce2 Ti"}, \
|
||||
{0x10DE, 0x0152, NV10, "NVidia GeForce2 Ultra"}, \
|
||||
{0x10DE, 0x0153, NV10, "NVidia Quadro2 Pro"}, \
|
||||
{0x10DE, 0x0170, NV10, "NVidia GeForce4 MX 460"}, \
|
||||
{0x10DE, 0x0171, NV10, "NVidia GeForce4 MX 440"}, \
|
||||
{0x10DE, 0x0172, NV10, "NVidia GeForce4 MX 420"}, \
|
||||
{0x10DE, 0x0173, NV10, "NVidia GeForce4 MX 440-SE"}, \
|
||||
{0x10DE, 0x0174, NV10, "NVidia GeForce4 440 Go"}, \
|
||||
{0x10DE, 0x0175, NV10, "NVidia GeForce4 420 Go"}, \
|
||||
{0x10DE, 0x0176, NV10, "NVidia GeForce4 420 Go 32M"}, \
|
||||
{0x10DE, 0x0177, NV10, "NVidia GeForce4 460 Go"}, \
|
||||
{0x10DE, 0x0178, NV10, "NVidia Quadro4 550 XGL"}, \
|
||||
{0x10DE, 0x0179, NV10, "NVidia GeForce4"}, \
|
||||
{0x10DE, 0x017A, NV10, "NVidia Quadro4 NVS"}, \
|
||||
{0x10DE, 0x017C, NV10, "NVidia Quadro4 500 GoGL"}, \
|
||||
{0x10DE, 0x017D, NV10, "NVidia GeForce4 410 Go 16M"}, \
|
||||
{0x10DE, 0x0181, NV10, "NVidia GeForce4 MX 440 with AGP8X"}, \
|
||||
{0x10DE, 0x0182, NV10, "NVidia GeForce4 MX 440SE with AGP8X"}, \
|
||||
{0x10DE, 0x0183, NV10, "NVidia GeForce4 MX 420 with AGP8X"}, \
|
||||
{0x10DE, 0x0185, NV10, "NVidia GeForce4 MX 4000"}, \
|
||||
{0x10DE, 0x0186, NV10, "NVidia GeForce4 448 Go"}, \
|
||||
{0x10DE, 0x0187, NV10, "NVidia GeForce4 488 Go"}, \
|
||||
{0x10DE, 0x0188, NV10, "NVidia Quadro4 580 XGL"}, \
|
||||
{0x10DE, 0x0189, NV10, "NVidia GeForce4 MX with AGP8X (Mac)"}, \
|
||||
{0x10DE, 0x018A, NV10, "NVidia Quadro4 280 NVS"}, \
|
||||
{0x10DE, 0x018B, NV10, "NVidia Quadro4 380 XGL"}, \
|
||||
{0x10DE, 0x018C, NV10, "NVidia Quadro NVS 50 PCI"}, \
|
||||
{0x10DE, 0x018D, NV10, "NVidia GeForce4 448 Go"}, \
|
||||
{0x10DE, 0x01A0, NV10, "NVidia GeForce2 Integrated GPU"}, \
|
||||
{0x10DE, 0x01F0, NV10, "NVidia GeForce4 MX Integrated GPU"}, \
|
||||
{0x10DE, 0x0200, NV20, "NVidia GeForce3"}, \
|
||||
{0x10DE, 0x0201, NV20, "NVidia GeForce3 Ti 200"}, \
|
||||
{0x10DE, 0x0202, NV20, "NVidia GeForce3 Ti 500"}, \
|
||||
{0x10DE, 0x0203, NV20, "NVidia Quadro DCC"}, \
|
||||
{0x10DE, 0x0250, NV20, "NVidia GeForce4 Ti 4600"}, \
|
||||
{0x10DE, 0x0251, NV20, "NVidia GeForce4 Ti 4400"}, \
|
||||
{0x10DE, 0x0252, NV20, "NVidia 0x0252"}, \
|
||||
{0x10DE, 0x0253, NV20, "NVidia GeForce4 Ti 4200"}, \
|
||||
{0x10DE, 0x0258, NV20, "NVidia Quadro4 900 XGL"}, \
|
||||
{0x10DE, 0x0259, NV20, "NVidia Quadro4 750 XGL"}, \
|
||||
{0x10DE, 0x025B, NV20, "NVidia Quadro4 700 XGL"}, \
|
||||
{0x10DE, 0x0280, NV20, "NVidia GeForce4 Ti 4800"}, \
|
||||
{0x10DE, 0x0281, NV20, "NVidia GeForce4 Ti 4200 with AGP8X"}, \
|
||||
{0x10DE, 0x0282, NV20, "NVidia GeForce4 Ti 4800 SE"}, \
|
||||
{0x10DE, 0x0286, NV20, "NVidia GeForce4 4200 Go"}, \
|
||||
{0x10DE, 0x028C, NV20, "NVidia Quadro4 700 GoGL"}, \
|
||||
{0x10DE, 0x0288, NV20, "NVidia Quadro4 980 XGL"}, \
|
||||
{0x10DE, 0x0289, NV20, "NVidia Quadro4 780 XGL"}, \
|
||||
{0x10DE, 0x0301, NV30, "NVidia GeForce FX 5800 Ultra"}, \
|
||||
{0x10DE, 0x0302, NV30, "NVidia GeForce FX 5800"}, \
|
||||
{0x10DE, 0x0308, NV30, "NVidia Quadro FX 2000"}, \
|
||||
{0x10DE, 0x0309, NV30, "NVidia Quadro FX 1000"}, \
|
||||
{0x10DE, 0x0311, NV30, "NVidia GeForce FX 5600 Ultra"}, \
|
||||
{0x10DE, 0x0312, NV30, "NVidia GeForce FX 5600"}, \
|
||||
{0x10DE, 0x0313, NV30, "NVidia 0x0313"},}, \
|
||||
{0x10DE, 0x0314, NV30, "NVidia GeForce FX 5600SE"}, \
|
||||
{0x10DE, 0x0316, NV30, "NVidia 0x0316"}, \
|
||||
{0x10DE, 0x0317, NV30, "NVidia 0x0317"}, \
|
||||
{0x10DE, 0x031A, NV30, "NVidia GeForce FX Go5600"}, \
|
||||
{0x10DE, 0x031B, NV30, "NVidia GeForce FX Go5650"}, \
|
||||
{0x10DE, 0x031C, NV30, "NVidia Quadro FX Go700"}, \
|
||||
{0x10DE, 0x031D, NV30, "NVidia 0x031D"}, \
|
||||
{0x10DE, 0x031E, NV30, "NVidia 0x031E"}, \
|
||||
{0x10DE, 0x031F, NV30, "NVidia 0x031F"}, \
|
||||
{0x10DE, 0x0320, NV30, "NVidia GeForce FX 5200"}, \
|
||||
{0x10DE, 0x0321, NV30, "NVidia GeForce FX 5200 Ultra"}, \
|
||||
{0x10DE, 0x0322, NV30, "NVidia GeForce FX 5200"}, \
|
||||
{0x10DE, 0x0323, NV30, "NVidia GeForce FX 5200SE"}, \
|
||||
{0x10DE, 0x0324, NV30, "NVidia GeForce FX Go5200"}, \
|
||||
{0x10DE, 0x0325, NV30, "NVidia GeForce FX Go5250"}, \
|
||||
{0x10DE, 0x0326, NV30, "NVidia GeForce FX 5500"}, \
|
||||
{0x10DE, 0x0327, NV30, "NVidia GeForce FX 5100"}, \
|
||||
{0x10DE, 0x0328, NV30, "NVidia GeForce FX Go5200 32M/64M"}, \
|
||||
{0x10DE, 0x0329, NV30, "NVidia GeForce FX 5200 (Mac)"}, \
|
||||
{0x10DE, 0x032A, NV30, "NVidia Quadro NVS 280 PCI"}, \
|
||||
{0x10DE, 0x032B, NV30, "NVidia Quadro FX 500/600 PCI"}, \
|
||||
{0x10DE, 0x032C, NV30, "NVidia GeForce FX Go53xx Series"}, \
|
||||
{0x10DE, 0x032D, NV30, "NVidia GeForce FX Go5100"}, \
|
||||
{0x10DE, 0x032F, NV30, "NVidia 0x032F"}, \
|
||||
{0x10DE, 0x0330, NV30, "NVidia GeForce FX 5900 Ultra"}, \
|
||||
{0x10DE, 0x0331, NV30, "NVidia GeForce FX 5900"}, \
|
||||
{0x10DE, 0x0332, NV30, "NVidia GeForce FX 5900XT"}, \
|
||||
{0x10DE, 0x0333, NV30, "NVidia GeForce FX 5950 Ultra"}, \
|
||||
{0x10DE, 0x033F, NV30, "NVidia Quadro FX 700"}, \
|
||||
{0x10DE, 0x0334, NV30, "NVidia GeForce FX 5900ZT"}, \
|
||||
{0x10DE, 0x0338, NV30, "NVidia Quadro FX 3000"}, \
|
||||
{0x10DE, 0x0341, NV30, "NVidia GeForce FX 5700 Ultra"}, \
|
||||
{0x10DE, 0x0342, NV30, "NVidia GeForce FX 5700"}, \
|
||||
{0x10DE, 0x0343, NV30, "NVidia GeForce FX 5700LE"}, \
|
||||
{0x10DE, 0x0344, NV30, "NVidia GeForce FX 5700VE"}, \
|
||||
{0x10DE, 0x0345, NV30, "NVidia 0x0345"}, \
|
||||
{0x10DE, 0x0347, NV30, "NVidia GeForce FX Go5700"}, \
|
||||
{0x10DE, 0x0348, NV30, "NVidia GeForce FX Go5700"}, \
|
||||
{0x10DE, 0x0349, NV30, "NVidia 0x0349"}, \
|
||||
{0x10DE, 0x034B, NV30, "NVidia 0x034B"}, \
|
||||
{0x10DE, 0x034C, NV30, "NVidia Quadro FX Go1000"}, \
|
||||
{0x10DE, 0x034E, NV30, "NVidia Quadro FX 1100"}, \
|
||||
{0x10DE, 0x034F, NV30, "NVidia 0x034F"}, \
|
||||
{0x10DE, 0x0040, NV40, "NVidia GeForce 6800 Ultra"}, \
|
||||
{0x10DE, 0x0041, NV40, "NVidia GeForce 6800"}, \
|
||||
{0x10DE, 0x0042, NV40, "NVidia GeForce 6800 LE"}, \
|
||||
{0x10DE, 0x0043, NV40, "NVidia 0x0043"}, \
|
||||
{0x10DE, 0x0045, NV40, "NVidia GeForce 6800 GT"}, \
|
||||
{0x10DE, 0x0046, NV40, "NVidia GeForce 6800 GT"}, \
|
||||
{0x10DE, 0x0049, NV40, "NVidia 0x0049"}, \
|
||||
{0x10DE, 0x004E, NV40, "NVidia Quadro FX 4000"}, \
|
||||
{0x10DE, 0x00C0, NV40, "NVidia 0x00C0"}, \
|
||||
{0x10DE, 0x00C1, NV40, "NVidia GeForce 6800"}, \
|
||||
{0x10DE, 0x00C2, NV40, "NVidia GeForce 6800 LE"}, \
|
||||
{0x10DE, 0x00C8, NV40, "NVidia GeForce Go 6800"}, \
|
||||
{0x10DE, 0x00C9, NV40, "NVidia GeForce Go 6800 Ultra"}, \
|
||||
{0x10DE, 0x00CC, NV40, "NVidia Quadro FX Go1400"}, \
|
||||
{0x10DE, 0x00CD, NV40, "NVidia Quadro FX 3450/4000 SDI"}, \
|
||||
{0x10DE, 0x00CE, NV40, "NVidia Quadro FX 1400"}, \
|
||||
{0x10de, 0x00f0, NV40, "Nvidia GeForce 6600 GT"}, \
|
||||
{0x10de, 0x00f1, NV40, "Nvidia GeForce 6600 GT"}, \
|
||||
{0x10DE, 0x0140, NV40, "NVidia GeForce 6600 GT"}, \
|
||||
{0x10DE, 0x0141, NV40, "NVidia GeForce 6600"}, \
|
||||
{0x10DE, 0x0142, NV40, "NVidia GeForce 6600 LE"}, \
|
||||
{0x10DE, 0x0143, NV40, "NVidia 0x0143"}, \
|
||||
{0x10DE, 0x0144, NV40, "NVidia GeForce Go 6600"}, \
|
||||
{0x10DE, 0x0145, NV40, "NVidia GeForce 6610 XL"}, \
|
||||
{0x10DE, 0x0146, NV40, "NVidia GeForce Go 6600 TE/6200 TE"}, \
|
||||
{0x10DE, 0x0147, NV40, "NVidia GeForce 6700 XL"}, \
|
||||
{0x10DE, 0x0148, NV40, "NVidia GeForce Go 6600"}, \
|
||||
{0x10DE, 0x0149, NV40, "NVidia GeForce Go 6600 GT"}, \
|
||||
{0x10DE, 0x014B, NV40, "NVidia 0x014B"}, \
|
||||
{0x10DE, 0x014C, NV40, "NVidia 0x014C"}, \
|
||||
{0x10DE, 0x014D, NV40, "NVidia 0x014D"}, \
|
||||
{0x10DE, 0x014E, NV40, "NVidia Quadro FX 540"}, \
|
||||
{0x10DE, 0x014F, NV40, "NVidia GeForce 6200"}, \
|
||||
{0x10DE, 0x0160, NV40, "NVidia 0x0160"}, \
|
||||
{0x10DE, 0x0161, NV40, "NVidia GeForce 6200 TurboCache(TM)"}, \
|
||||
{0x10DE, 0x0162, NV40, "NVidia GeForce 6200SE TurboCache(TM)"}, \
|
||||
{0x10DE, 0x0163, NV40, "NVidia 0x0163"}, \
|
||||
{0x10DE, 0x0164, NV40, "NVidia GeForce Go 6200"}, \
|
||||
{0x10DE, 0x0165, NV40, "NVidia Quadro NVS 285"}, \
|
||||
{0x10DE, 0x0166, NV40, "NVidia GeForce Go 6400"}, \
|
||||
{0x10DE, 0x0167, NV40, "NVidia GeForce Go 6200"}, \
|
||||
{0x10DE, 0x0168, NV40, "NVidia GeForce Go 6400"}, \
|
||||
{0x10DE, 0x0169, NV40, "NVidia 0x0169"}, \
|
||||
{0x10DE, 0x016B, NV40, "NVidia 0x016B"}, \
|
||||
{0x10DE, 0x016C, NV40, "NVidia 0x016C"}, \
|
||||
{0x10DE, 0x016D, NV40, "NVidia 0x016D"}, \
|
||||
{0x10DE, 0x016E, NV40, "NVidia 0x016E"}, \
|
||||
{0x10DE, 0x0210, NV40, "NVidia 0x0210"}, \
|
||||
{0x10DE, 0x0211, NV40, "NVidia GeForce 6800"}, \
|
||||
{0x10DE, 0x0212, NV40, "NVidia GeForce 6800 LE"}, \
|
||||
{0x10DE, 0x0215, NV40, "NVidia GeForce 6800 GT"}, \
|
||||
{0x10DE, 0x0220, NV40, "NVidia 0x0220"}, \
|
||||
{0x10DE, 0x0221, NV40, "NVidia GeForce 6200"}, \
|
||||
{0x10DE, 0x0222, NV40, "NVidia 0x0222"}, \
|
||||
{0x10DE, 0x0228, NV40, "NVidia 0x0228"}, \
|
||||
{0x10DE, 0x0090, NV40, "NVidia 0x0090"}, \
|
||||
{0x10DE, 0x0091, NV40, "NVidia GeForce 7800 GTX"}, \
|
||||
{0x10DE, 0x0092, NV40, "NVidia 0x0092"}, \
|
||||
{0x10DE, 0x0093, NV40, "NVidia 0x0093"}, \
|
||||
{0x10DE, 0x0094, NV40, "NVidia 0x0094"}, \
|
||||
{0x10DE, 0x0098, NV40, "NVidia 0x0098"}, \
|
||||
{0x10DE, 0x0099, NV40, "NVidia GeForce Go 7800 GTX"}, \
|
||||
{0x10DE, 0x009C, NV40, "NVidia 0x009C"}, \
|
||||
{0x10DE, 0x009D, NV40, "NVidia Quadro FX 4500"}, \
|
||||
{0x10DE, 0x009E, NV40, "NVidia 0x009E"}, \
|
||||
{0, 0, 0, NULL}
|
|
@ -0,0 +1,823 @@
|
|||
/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/i915_dma.c,v 1.4 2006/09/07 23:04:47 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include <dev/drm/drmP.h>
|
||||
#include <dev/drm/drm.h>
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
|
||||
dev->pci_device == 0x2982 || \
|
||||
dev->pci_device == 0x2992 || \
|
||||
dev->pci_device == 0x29A2)
|
||||
|
||||
|
||||
/* Really want an OS-independent resettable timer. Would like to have
|
||||
* this loop run for (eg) 3 sec, but have the timer reset every time
|
||||
* the head pointer changes, so that EBUSY only happens if the ring
|
||||
* actually stalls for (eg) 3 seconds.
|
||||
*/
|
||||
int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10000; i++) {
|
||||
ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
|
||||
ring->space = ring->head - (ring->tail + 8);
|
||||
if (ring->space < 0)
|
||||
ring->space += ring->Size;
|
||||
if (ring->space >= n)
|
||||
return 0;
|
||||
|
||||
dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
|
||||
if (ring->head != last_head)
|
||||
i = 0;
|
||||
|
||||
last_head = ring->head;
|
||||
}
|
||||
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
|
||||
void i915_kernel_lost_context(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
|
||||
ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
|
||||
ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
|
||||
ring->space = ring->head - (ring->tail + 8);
|
||||
if (ring->space < 0)
|
||||
ring->space += ring->Size;
|
||||
|
||||
if (ring->head == ring->tail)
|
||||
dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
|
||||
}
|
||||
|
||||
static int i915_dma_cleanup(drm_device_t * dev)
|
||||
{
|
||||
/* Make sure interrupts are disabled here because the uninstall ioctl
|
||||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq)
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv =
|
||||
(drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
if (dev_priv->ring.virtual_start) {
|
||||
drm_core_ioremapfree(&dev_priv->ring.map, dev);
|
||||
}
|
||||
|
||||
if (dev_priv->status_page_dmah) {
|
||||
drm_pci_free(dev, dev_priv->status_page_dmah);
|
||||
/* Need to rewrite hardware status page */
|
||||
I915_WRITE(0x02080, 0x1ffff000);
|
||||
}
|
||||
|
||||
drm_free(dev->dev_private, sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
|
||||
dev->dev_private = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_initialize(drm_device_t * dev,
|
||||
drm_i915_private_t * dev_priv,
|
||||
drm_i915_init_t * init)
|
||||
{
|
||||
memset(dev_priv, 0, sizeof(drm_i915_private_t));
|
||||
|
||||
DRM_GETSAREA();
|
||||
if (!dev_priv->sarea) {
|
||||
DRM_ERROR("can not find sarea!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
i915_dma_cleanup(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
|
||||
if (!dev_priv->mmio_map) {
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
i915_dma_cleanup(dev);
|
||||
DRM_ERROR("can not find mmio map!\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->sarea_priv = (drm_i915_sarea_t *)
|
||||
((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
|
||||
|
||||
dev_priv->ring.Start = init->ring_start;
|
||||
dev_priv->ring.End = init->ring_end;
|
||||
dev_priv->ring.Size = init->ring_size;
|
||||
dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
|
||||
|
||||
dev_priv->ring.map.offset = init->ring_start;
|
||||
dev_priv->ring.map.size = init->ring_size;
|
||||
dev_priv->ring.map.type = 0;
|
||||
dev_priv->ring.map.flags = 0;
|
||||
dev_priv->ring.map.mtrr = 0;
|
||||
|
||||
drm_core_ioremap(&dev_priv->ring.map, dev);
|
||||
|
||||
if (dev_priv->ring.map.handle == NULL) {
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
i915_dma_cleanup(dev);
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
" ring buffer\n");
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
|
||||
|
||||
dev_priv->back_offset = init->back_offset;
|
||||
dev_priv->front_offset = init->front_offset;
|
||||
dev_priv->current_page = 0;
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
|
||||
/* We are using separate values as placeholders for mechanisms for
|
||||
* private backbuffer/depthbuffer usage.
|
||||
*/
|
||||
dev_priv->use_mi_batchbuffer_start = 0;
|
||||
|
||||
/* Allow hardware batchbuffers unless told otherwise.
|
||||
*/
|
||||
dev_priv->allow_batchbuffer = 1;
|
||||
|
||||
/* Program Hardware Status Page */
|
||||
dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
|
||||
0xffffffff);
|
||||
|
||||
if (!dev_priv->status_page_dmah) {
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
i915_dma_cleanup(dev);
|
||||
DRM_ERROR("Can not allocate hardware status page\n");
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
|
||||
dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
|
||||
|
||||
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
|
||||
|
||||
I915_WRITE(0x02080, dev_priv->dma_status_page);
|
||||
DRM_DEBUG("Enabled hardware status page\n");
|
||||
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_dma_resume(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
if (!dev_priv->sarea) {
|
||||
DRM_ERROR("can not find sarea!\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (!dev_priv->mmio_map) {
|
||||
DRM_ERROR("can not find mmio map!\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (dev_priv->ring.map.handle == NULL) {
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
" ring buffer\n");
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
/* Program Hardware Status Page */
|
||||
if (!dev_priv->hw_status_page) {
|
||||
DRM_ERROR("Can not find hardware status page\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
|
||||
|
||||
I915_WRITE(0x02080, dev_priv->dma_status_page);
|
||||
DRM_DEBUG("Enabled hardware status page\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_dma_init(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv;
|
||||
drm_i915_init_t init;
|
||||
int retcode = 0;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data,
|
||||
sizeof(init));
|
||||
|
||||
switch (init.func) {
|
||||
case I915_INIT_DMA:
|
||||
dev_priv = drm_alloc(sizeof(drm_i915_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
if (dev_priv == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
retcode = i915_initialize(dev, dev_priv, &init);
|
||||
break;
|
||||
case I915_CLEANUP_DMA:
|
||||
retcode = i915_dma_cleanup(dev);
|
||||
break;
|
||||
case I915_RESUME_DMA:
|
||||
retcode = i915_dma_resume(dev);
|
||||
break;
|
||||
default:
|
||||
retcode = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/* Implement basically the same security restrictions as hardware does
|
||||
* for MI_BATCH_NON_SECURE. These can be made stricter at any time.
|
||||
*
|
||||
* Most of the calculations below involve calculating the size of a
|
||||
* particular instruction. It's important to get the size right as
|
||||
* that tells us where the next instruction to check is. Any illegal
|
||||
* instruction detected will be given a size of zero, which is a
|
||||
* signal to abort the rest of the buffer.
|
||||
*/
|
||||
static int do_validate_cmd(int cmd)
|
||||
{
|
||||
switch (((cmd >> 29) & 0x7)) {
|
||||
case 0x0:
|
||||
switch ((cmd >> 23) & 0x3f) {
|
||||
case 0x0:
|
||||
return 1; /* MI_NOOP */
|
||||
case 0x4:
|
||||
return 1; /* MI_FLUSH */
|
||||
default:
|
||||
return 0; /* disallow everything else */
|
||||
}
|
||||
break;
|
||||
case 0x1:
|
||||
return 0; /* reserved */
|
||||
case 0x2:
|
||||
return (cmd & 0xff) + 2; /* 2d commands */
|
||||
case 0x3:
|
||||
if (((cmd >> 24) & 0x1f) <= 0x18)
|
||||
return 1;
|
||||
|
||||
switch ((cmd >> 24) & 0x1f) {
|
||||
case 0x1c:
|
||||
return 1;
|
||||
case 0x1d:
|
||||
switch ((cmd >> 16) & 0xff) {
|
||||
case 0x3:
|
||||
return (cmd & 0x1f) + 2;
|
||||
case 0x4:
|
||||
return (cmd & 0xf) + 2;
|
||||
default:
|
||||
return (cmd & 0xffff) + 2;
|
||||
}
|
||||
case 0x1e:
|
||||
if (cmd & (1 << 23))
|
||||
return (cmd & 0xffff) + 1;
|
||||
else
|
||||
return 1;
|
||||
case 0x1f:
|
||||
if ((cmd & (1 << 23)) == 0) /* inline vertices */
|
||||
return (cmd & 0x1ffff) + 2;
|
||||
else if (cmd & (1 << 17)) /* indirect random */
|
||||
if ((cmd & 0xffff) == 0)
|
||||
return 0; /* unknown length, too hard */
|
||||
else
|
||||
return (((cmd & 0xffff) + 1) / 2) + 1;
|
||||
else
|
||||
return 2; /* indirect sequential */
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate_cmd(int cmd)
|
||||
{
|
||||
int ret = do_validate_cmd(cmd);
|
||||
|
||||
/* printk("validate_cmd( %x ): %d\n", cmd, ret); */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
RING_LOCALS;
|
||||
|
||||
if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
BEGIN_LP_RING((dwords+1)&~1);
|
||||
|
||||
for (i = 0; i < dwords;) {
|
||||
int cmd, sz;
|
||||
|
||||
if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) {
|
||||
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
OUT_RING(cmd);
|
||||
|
||||
while (++i, --sz) {
|
||||
if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
|
||||
sizeof(cmd))) {
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
OUT_RING(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (dwords & 1)
|
||||
OUT_RING(0);
|
||||
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_emit_box(drm_device_t * dev,
|
||||
drm_clip_rect_t __user * boxes,
|
||||
int i, int DR1, int DR4)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_clip_rect_t box;
|
||||
RING_LOCALS;
|
||||
|
||||
if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
|
||||
DRM_ERROR("Bad box %d,%d..%d,%d\n",
|
||||
box.x1, box.y1, box.x2, box.y2);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
|
||||
OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
|
||||
OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
|
||||
OUT_RING(DR4);
|
||||
ADVANCE_LP_RING();
|
||||
} else {
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(GFX_OP_DRAWRECT_INFO);
|
||||
OUT_RING(DR1);
|
||||
OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
|
||||
OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
|
||||
OUT_RING(DR4);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX: Emitting the counter should really be moved to part of the IRQ
|
||||
* emit. For now, do it in both places:
|
||||
*/
|
||||
|
||||
static void i915_emit_breadcrumb(drm_device_t *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
|
||||
dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
|
||||
|
||||
if (dev_priv->counter > 0x7FFFFFFFUL)
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
OUT_RING(20);
|
||||
OUT_RING(dev_priv->counter);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
static int i915_dispatch_cmdbuffer(drm_device_t * dev,
|
||||
drm_i915_cmdbuffer_t * cmd)
|
||||
{
|
||||
int nbox = cmd->num_cliprects;
|
||||
int i = 0, count, ret;
|
||||
|
||||
if (cmd->sz & 0x3) {
|
||||
DRM_ERROR("alignment");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
count = nbox ? nbox : 1;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i < nbox) {
|
||||
ret = i915_emit_box(dev, cmd->cliprects, i,
|
||||
cmd->DR1, cmd->DR4);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
i915_emit_breadcrumb( dev );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_dispatch_batchbuffer(drm_device_t * dev,
|
||||
drm_i915_batchbuffer_t * batch)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_clip_rect_t __user *boxes = batch->cliprects;
|
||||
int nbox = batch->num_cliprects;
|
||||
int i = 0, count;
|
||||
RING_LOCALS;
|
||||
|
||||
if ((batch->start | batch->used) & 0x7) {
|
||||
DRM_ERROR("alignment");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
count = nbox ? nbox : 1;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i < nbox) {
|
||||
int ret = i915_emit_box(dev, boxes, i,
|
||||
batch->DR1, batch->DR4);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dev_priv->use_mi_batchbuffer_start) {
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
|
||||
OUT_RING(batch->start | MI_BATCH_NON_SECURE);
|
||||
ADVANCE_LP_RING();
|
||||
} else {
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_BATCH_BUFFER);
|
||||
OUT_RING(batch->start | MI_BATCH_NON_SECURE);
|
||||
OUT_RING(batch->start + batch->used - 4);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
}
|
||||
|
||||
i915_emit_breadcrumb( dev );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_dispatch_flip(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
|
||||
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
|
||||
__FUNCTION__,
|
||||
dev_priv->current_page,
|
||||
dev_priv->sarea_priv->pf_current_page);
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
|
||||
OUT_RING(0);
|
||||
if (dev_priv->current_page == 0) {
|
||||
OUT_RING(dev_priv->back_offset);
|
||||
dev_priv->current_page = 1;
|
||||
} else {
|
||||
OUT_RING(dev_priv->front_offset);
|
||||
dev_priv->current_page = 0;
|
||||
}
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
OUT_RING(20);
|
||||
OUT_RING(dev_priv->counter);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_quiescent(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
|
||||
}
|
||||
|
||||
static int i915_flush_ioctl(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
return i915_quiescent(dev);
|
||||
}
|
||||
|
||||
static int i915_batchbuffer(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 *hw_status = dev_priv->hw_status_page;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
drm_i915_batchbuffer_t batch;
|
||||
int ret;
|
||||
|
||||
if (!dev_priv->allow_batchbuffer) {
|
||||
DRM_ERROR("Batchbuffer ioctl disabled\n");
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data,
|
||||
sizeof(batch));
|
||||
|
||||
DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
|
||||
batch.start, batch.used, batch.num_cliprects);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
|
||||
batch.num_cliprects *
|
||||
sizeof(drm_clip_rect_t)))
|
||||
return DRM_ERR(EFAULT);
|
||||
|
||||
ret = i915_dispatch_batchbuffer(dev, &batch);
|
||||
|
||||
sarea_priv->last_dispatch = (int)hw_status[5];
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_cmdbuffer(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 *hw_status = dev_priv->hw_status_page;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
drm_i915_cmdbuffer_t cmdbuf;
|
||||
int ret;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data,
|
||||
sizeof(cmdbuf));
|
||||
|
||||
DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
|
||||
cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (cmdbuf.num_cliprects &&
|
||||
DRM_VERIFYAREA_READ(cmdbuf.cliprects,
|
||||
cmdbuf.num_cliprects *
|
||||
sizeof(drm_clip_rect_t))) {
|
||||
DRM_ERROR("Fault accessing cliprects\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
|
||||
if (ret) {
|
||||
DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
sarea_priv->last_dispatch = (int)hw_status[5];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_do_cleanup_pageflip(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
if (dev_priv->current_page != 0)
|
||||
i915_dispatch_flip(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_flip_bufs(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
return i915_dispatch_flip(dev);
|
||||
}
|
||||
|
||||
static int i915_getparam(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_getparam_t param;
|
||||
int value;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data,
|
||||
sizeof(param));
|
||||
|
||||
switch (param.param) {
|
||||
case I915_PARAM_IRQ_ACTIVE:
|
||||
value = dev->irq ? 1 : 0;
|
||||
break;
|
||||
case I915_PARAM_ALLOW_BATCHBUFFER:
|
||||
value = dev_priv->allow_batchbuffer ? 1 : 0;
|
||||
break;
|
||||
case I915_PARAM_LAST_DISPATCH:
|
||||
value = READ_BREADCRUMB(dev_priv);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown parameter %d\n", param.param);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
|
||||
DRM_ERROR("DRM_COPY_TO_USER failed\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_setparam(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_setparam_t param;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data,
|
||||
sizeof(param));
|
||||
|
||||
switch (param.param) {
|
||||
case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
|
||||
dev_priv->use_mi_batchbuffer_start = param.value;
|
||||
break;
|
||||
case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
|
||||
dev_priv->tex_lru_log_granularity = param.value;
|
||||
break;
|
||||
case I915_SETPARAM_ALLOW_BATCHBUFFER:
|
||||
dev_priv->allow_batchbuffer = param.value;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unknown parameter %d\n", param.param);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_driver_load(drm_device_t *dev, unsigned long flags)
|
||||
{
|
||||
/* i915 has 4 more counters */
|
||||
dev->counters += 4;
|
||||
dev->types[6] = _DRM_STAT_IRQ;
|
||||
dev->types[7] = _DRM_STAT_PRIMARY;
|
||||
dev->types[8] = _DRM_STAT_SECONDARY;
|
||||
dev->types[9] = _DRM_STAT_DMA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_driver_lastclose(drm_device_t * dev)
|
||||
{
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
i915_mem_takedown(&(dev_priv->agp_heap));
|
||||
}
|
||||
i915_dma_cleanup(dev);
|
||||
}
|
||||
|
||||
void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
|
||||
{
|
||||
if (dev->dev_private) {
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
if (dev_priv->page_flipping) {
|
||||
i915_do_cleanup_pageflip(dev);
|
||||
}
|
||||
i915_mem_release(dev, filp, dev_priv->agp_heap);
|
||||
}
|
||||
}
|
||||
|
||||
drm_ioctl_desc_t i915_ioctls[] = {
|
||||
[DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
|
||||
[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
|
||||
[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
|
||||
};
|
||||
|
||||
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
|
||||
|
||||
/**
|
||||
* Determine if the device really is AGP or not.
|
||||
*
|
||||
* All Intel graphics chipsets are treated as AGP, even if they are really
|
||||
* PCI-e.
|
||||
*
|
||||
* \param dev The device to be tested.
|
||||
*
|
||||
* \returns
|
||||
* A value of 1 is always retured to indictate every i9x5 is AGP.
|
||||
*/
|
||||
int i915_driver_device_is_agp(drm_device_t * dev)
|
||||
{
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/*-
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/i915_drm.h,v 1.4 2006/09/07 23:04:47 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef _I915_DRM_H_
|
||||
#define _I915_DRM_H_
|
||||
|
||||
/* Please note that modifications to all structs defined here are
|
||||
* subject to backwards-compatibility constraints.
|
||||
*/
|
||||
|
||||
#include <dev/drm/drm.h>
|
||||
|
||||
/* Each region is a minimum of 16k, and there are at most 255 of them.
|
||||
*/
|
||||
#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
|
||||
* of chars for next/prev indices */
|
||||
#define I915_LOG_MIN_TEX_REGION_SIZE 14
|
||||
|
||||
typedef struct _drm_i915_init {
|
||||
enum {
|
||||
I915_INIT_DMA = 0x01,
|
||||
I915_CLEANUP_DMA = 0x02,
|
||||
I915_RESUME_DMA = 0x03
|
||||
} func;
|
||||
unsigned int mmio_offset;
|
||||
int sarea_priv_offset;
|
||||
unsigned int ring_start;
|
||||
unsigned int ring_end;
|
||||
unsigned int ring_size;
|
||||
unsigned int front_offset;
|
||||
unsigned int back_offset;
|
||||
unsigned int depth_offset;
|
||||
unsigned int w;
|
||||
unsigned int h;
|
||||
unsigned int pitch;
|
||||
unsigned int pitch_bits;
|
||||
unsigned int back_pitch;
|
||||
unsigned int depth_pitch;
|
||||
unsigned int cpp;
|
||||
unsigned int chipset;
|
||||
} drm_i915_init_t;
|
||||
|
||||
typedef struct _drm_i915_sarea {
|
||||
drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1];
|
||||
int last_upload; /* last time texture was uploaded */
|
||||
int last_enqueue; /* last time a buffer was enqueued */
|
||||
int last_dispatch; /* age of the most recently dispatched buffer */
|
||||
int ctxOwner; /* last context to upload state */
|
||||
int texAge;
|
||||
int pf_enabled; /* is pageflipping allowed? */
|
||||
int pf_active;
|
||||
int pf_current_page; /* which buffer is being displayed? */
|
||||
int perf_boxes; /* performance boxes to be displayed */
|
||||
int width, height; /* screen size in pixels */
|
||||
|
||||
drm_handle_t front_handle;
|
||||
int front_offset;
|
||||
int front_size;
|
||||
|
||||
drm_handle_t back_handle;
|
||||
int back_offset;
|
||||
int back_size;
|
||||
|
||||
drm_handle_t depth_handle;
|
||||
int depth_offset;
|
||||
int depth_size;
|
||||
|
||||
drm_handle_t tex_handle;
|
||||
int tex_offset;
|
||||
int tex_size;
|
||||
int log_tex_granularity;
|
||||
int pitch;
|
||||
int rotation; /* 0, 90, 180 or 270 */
|
||||
int rotated_offset;
|
||||
int rotated_size;
|
||||
int rotated_pitch;
|
||||
int virtualX, virtualY;
|
||||
|
||||
unsigned int front_tiled;
|
||||
unsigned int back_tiled;
|
||||
unsigned int depth_tiled;
|
||||
unsigned int rotated_tiled;
|
||||
unsigned int rotated2_tiled;
|
||||
} drm_i915_sarea_t;
|
||||
|
||||
/* Flags for perf_boxes
|
||||
*/
|
||||
#define I915_BOX_RING_EMPTY 0x1
|
||||
#define I915_BOX_FLIP 0x2
|
||||
#define I915_BOX_WAIT 0x4
|
||||
#define I915_BOX_TEXTURE_LOAD 0x8
|
||||
#define I915_BOX_LOST_CONTEXT 0x10
|
||||
|
||||
/* I915 specific ioctls
|
||||
* The device specific ioctl range is 0x40 to 0x79.
|
||||
*/
|
||||
#define DRM_I915_INIT 0x00
|
||||
#define DRM_I915_FLUSH 0x01
|
||||
#define DRM_I915_FLIP 0x02
|
||||
#define DRM_I915_BATCHBUFFER 0x03
|
||||
#define DRM_I915_IRQ_EMIT 0x04
|
||||
#define DRM_I915_IRQ_WAIT 0x05
|
||||
#define DRM_I915_GETPARAM 0x06
|
||||
#define DRM_I915_SETPARAM 0x07
|
||||
#define DRM_I915_ALLOC 0x08
|
||||
#define DRM_I915_FREE 0x09
|
||||
#define DRM_I915_INIT_HEAP 0x0a
|
||||
#define DRM_I915_CMDBUFFER 0x0b
|
||||
#define DRM_I915_DESTROY_HEAP 0x0c
|
||||
#define DRM_I915_SET_VBLANK_PIPE 0x0d
|
||||
#define DRM_I915_GET_VBLANK_PIPE 0x0e
|
||||
|
||||
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
|
||||
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
|
||||
#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
|
||||
#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
|
||||
#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
|
||||
#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
|
||||
#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
|
||||
#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t)
|
||||
#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t)
|
||||
#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
|
||||
#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
|
||||
#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
|
||||
#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
|
||||
#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
|
||||
#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
|
||||
|
||||
|
||||
/* Allow drivers to submit batchbuffers directly to hardware, relying
|
||||
* on the security mechanisms provided by hardware.
|
||||
*/
|
||||
typedef struct _drm_i915_batchbuffer {
|
||||
int start; /* agp offset */
|
||||
int used; /* nr bytes in use */
|
||||
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
|
||||
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
|
||||
int num_cliprects; /* mulitpass with multiple cliprects? */
|
||||
drm_clip_rect_t __user *cliprects; /* pointer to userspace cliprects */
|
||||
} drm_i915_batchbuffer_t;
|
||||
|
||||
/* As above, but pass a pointer to userspace buffer which can be
|
||||
* validated by the kernel prior to sending to hardware.
|
||||
*/
|
||||
typedef struct _drm_i915_cmdbuffer {
|
||||
char __user *buf; /* pointer to userspace command buffer */
|
||||
int sz; /* nr bytes in buf */
|
||||
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
|
||||
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
|
||||
int num_cliprects; /* mulitpass with multiple cliprects? */
|
||||
drm_clip_rect_t __user *cliprects; /* pointer to userspace cliprects */
|
||||
} drm_i915_cmdbuffer_t;
|
||||
|
||||
/* Userspace can request & wait on irq's:
|
||||
*/
|
||||
typedef struct drm_i915_irq_emit {
|
||||
int __user *irq_seq;
|
||||
} drm_i915_irq_emit_t;
|
||||
|
||||
typedef struct drm_i915_irq_wait {
|
||||
int irq_seq;
|
||||
} drm_i915_irq_wait_t;
|
||||
|
||||
/* Ioctl to query kernel params:
|
||||
*/
|
||||
#define I915_PARAM_IRQ_ACTIVE 1
|
||||
#define I915_PARAM_ALLOW_BATCHBUFFER 2
|
||||
#define I915_PARAM_LAST_DISPATCH 3
|
||||
|
||||
typedef struct drm_i915_getparam {
|
||||
int param;
|
||||
int __user *value;
|
||||
} drm_i915_getparam_t;
|
||||
|
||||
/* Ioctl to set kernel params:
|
||||
*/
|
||||
#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1
|
||||
#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
|
||||
#define I915_SETPARAM_ALLOW_BATCHBUFFER 3
|
||||
|
||||
typedef struct drm_i915_setparam {
|
||||
int param;
|
||||
int value;
|
||||
} drm_i915_setparam_t;
|
||||
|
||||
/* A memory manager for regions of shared memory:
|
||||
*/
|
||||
#define I915_MEM_REGION_AGP 1
|
||||
|
||||
typedef struct drm_i915_mem_alloc {
|
||||
int region;
|
||||
int alignment;
|
||||
int size;
|
||||
int __user *region_offset; /* offset from start of fb or agp */
|
||||
} drm_i915_mem_alloc_t;
|
||||
|
||||
typedef struct drm_i915_mem_free {
|
||||
int region;
|
||||
int region_offset;
|
||||
} drm_i915_mem_free_t;
|
||||
|
||||
typedef struct drm_i915_mem_init_heap {
|
||||
int region;
|
||||
int size;
|
||||
int start;
|
||||
} drm_i915_mem_init_heap_t;
|
||||
|
||||
/* Allow memory manager to be torn down and re-initialized (eg on
|
||||
* rotate):
|
||||
*/
|
||||
typedef struct drm_i915_mem_destroy_heap {
|
||||
int region;
|
||||
} drm_i915_mem_destroy_heap_t;
|
||||
|
||||
/* Allow X server to configure which pipes to monitor for vblank signals
|
||||
*/
|
||||
#define DRM_I915_VBLANK_PIPE_A 1
|
||||
#define DRM_I915_VBLANK_PIPE_B 2
|
||||
|
||||
typedef struct drm_i915_vblank_pipe {
|
||||
int pipe;
|
||||
} drm_i915_vblank_pipe_t;
|
||||
|
||||
#endif /* _I915_DRM_H_ */
|
|
@ -0,0 +1,145 @@
|
|||
/* i915_drv.c -- ATI Radeon driver -*- linux-c -*-
|
||||
* Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/i915_drv.c,v 1.5 2006/05/17 06:36:28 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include <dev/drm/drmP.h>
|
||||
#include <dev/drm/drm.h>
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t i915_pciidlist[] = {
|
||||
i915_PCI_IDS
|
||||
};
|
||||
|
||||
static void i915_configure(drm_device_t *dev)
|
||||
{
|
||||
dev->driver.buf_priv_size = 1; /* No dev_priv */
|
||||
dev->driver.load = i915_driver_load;
|
||||
dev->driver.preclose = i915_driver_preclose;
|
||||
dev->driver.lastclose = i915_driver_lastclose;
|
||||
dev->driver.device_is_agp = i915_driver_device_is_agp,
|
||||
dev->driver.vblank_wait = i915_driver_vblank_wait;
|
||||
dev->driver.irq_preinstall = i915_driver_irq_preinstall;
|
||||
dev->driver.irq_postinstall = i915_driver_irq_postinstall;
|
||||
dev->driver.irq_uninstall = i915_driver_irq_uninstall;
|
||||
dev->driver.irq_handler = i915_driver_irq_handler;
|
||||
|
||||
dev->driver.ioctls = i915_ioctls;
|
||||
dev->driver.max_ioctl = i915_max_ioctl;
|
||||
|
||||
dev->driver.name = DRIVER_NAME;
|
||||
dev->driver.desc = DRIVER_DESC;
|
||||
dev->driver.date = DRIVER_DATE;
|
||||
dev->driver.major = DRIVER_MAJOR;
|
||||
dev->driver.minor = DRIVER_MINOR;
|
||||
dev->driver.patchlevel = DRIVER_PATCHLEVEL;
|
||||
|
||||
dev->driver.use_agp = 1;
|
||||
dev->driver.require_agp = 1;
|
||||
dev->driver.use_mtrr = 1;
|
||||
dev->driver.use_irq = 1;
|
||||
dev->driver.use_vbl_irq = 1;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
i915_probe(device_t dev)
|
||||
{
|
||||
return drm_probe(dev, i915_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
i915_attach(device_t nbdev)
|
||||
{
|
||||
drm_device_t *dev = device_get_softc(nbdev);
|
||||
|
||||
bzero(dev, sizeof(drm_device_t));
|
||||
i915_configure(dev);
|
||||
return drm_attach(nbdev, i915_pciidlist);
|
||||
}
|
||||
|
||||
static device_method_t i915_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, i915_probe),
|
||||
DEVMETHOD(device_attach, i915_attach),
|
||||
DEVMETHOD(device_detach, drm_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t i915_driver = {
|
||||
#if __FreeBSD_version >= 700010
|
||||
"drm",
|
||||
#else
|
||||
"drmsub",
|
||||
#endif
|
||||
i915_methods,
|
||||
sizeof(drm_device_t)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(i915, vgapci, i915_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(i915, agp, i915_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(i915, drm, 1, 1, 1);
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
static int
|
||||
i915drm_probe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
return drm_probe(pa, i915_pciidlist);
|
||||
}
|
||||
|
||||
static void
|
||||
i915drm_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
drm_device_t *dev = (drm_device_t *)self;
|
||||
|
||||
i915_configure(dev);
|
||||
|
||||
drm_attach(self, pa, i915_pciidlist);
|
||||
}
|
||||
|
||||
CFATTACH_DECL(i915drm, sizeof(drm_device_t), i915drm_probe, i915drm_attach,
|
||||
drm_detach, drm_activate);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,282 @@
|
|||
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/i915_drv.h,v 1.4 2006/09/07 23:04:47 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef _I915_DRV_H_
|
||||
#define _I915_DRV_H_
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
|
||||
#define DRIVER_AUTHOR "Tungsten Graphics, Inc."
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20060119"
|
||||
|
||||
/* Interface history:
|
||||
*
|
||||
* 1.1: Original.
|
||||
* 1.2: Add Power Management
|
||||
* 1.3: Add vblank support
|
||||
* 1.4: Fix cmdbuffer path, add heap destroy
|
||||
* 1.5: Add vblank pipe configuration
|
||||
*/
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 5
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
typedef struct _drm_i915_ring_buffer {
|
||||
int tail_mask;
|
||||
unsigned long Start;
|
||||
unsigned long End;
|
||||
unsigned long Size;
|
||||
u8 *virtual_start;
|
||||
int head;
|
||||
int tail;
|
||||
int space;
|
||||
drm_local_map_t map;
|
||||
} drm_i915_ring_buffer_t;
|
||||
|
||||
struct mem_block {
|
||||
struct mem_block *next;
|
||||
struct mem_block *prev;
|
||||
int start;
|
||||
int size;
|
||||
DRMFILE filp; /* 0: free, -1: heap, other: real files */
|
||||
};
|
||||
|
||||
typedef struct drm_i915_private {
|
||||
drm_local_map_t *sarea;
|
||||
drm_local_map_t *mmio_map;
|
||||
|
||||
drm_i915_sarea_t *sarea_priv;
|
||||
drm_i915_ring_buffer_t ring;
|
||||
|
||||
drm_dma_handle_t *status_page_dmah;
|
||||
void *hw_status_page;
|
||||
dma_addr_t dma_status_page;
|
||||
unsigned long counter;
|
||||
|
||||
int back_offset;
|
||||
int front_offset;
|
||||
int current_page;
|
||||
int page_flipping;
|
||||
int use_mi_batchbuffer_start;
|
||||
|
||||
wait_queue_head_t irq_queue;
|
||||
atomic_t irq_received;
|
||||
atomic_t irq_emitted;
|
||||
|
||||
int tex_lru_log_granularity;
|
||||
int allow_batchbuffer;
|
||||
struct mem_block *agp_heap;
|
||||
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
|
||||
int vblank_pipe;
|
||||
} drm_i915_private_t;
|
||||
|
||||
extern drm_ioctl_desc_t i915_ioctls[];
|
||||
extern int i915_max_ioctl;
|
||||
|
||||
/* i915_dma.c */
|
||||
extern void i915_kernel_lost_context(drm_device_t * dev);
|
||||
extern int i915_driver_load(struct drm_device *, unsigned long flags);
|
||||
extern void i915_driver_lastclose(drm_device_t * dev);
|
||||
extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
|
||||
extern int i915_driver_device_is_agp(drm_device_t * dev);
|
||||
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/* i915_irq.c */
|
||||
extern int i915_irq_emit(DRM_IOCTL_ARGS);
|
||||
extern int i915_irq_wait(DRM_IOCTL_ARGS);
|
||||
|
||||
extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
|
||||
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void i915_driver_irq_preinstall(drm_device_t * dev);
|
||||
extern void i915_driver_irq_postinstall(drm_device_t * dev);
|
||||
extern void i915_driver_irq_uninstall(drm_device_t * dev);
|
||||
extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
|
||||
extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
|
||||
|
||||
/* i915_mem.c */
|
||||
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
|
||||
extern int i915_mem_free(DRM_IOCTL_ARGS);
|
||||
extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
|
||||
extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
|
||||
extern void i915_mem_takedown(struct mem_block **heap);
|
||||
extern void i915_mem_release(drm_device_t * dev,
|
||||
DRMFILE filp, struct mem_block *heap);
|
||||
|
||||
#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))
|
||||
#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
|
||||
#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
|
||||
#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
|
||||
|
||||
#define I915_VERBOSE 0
|
||||
|
||||
#define RING_LOCALS unsigned int outring, ringmask, outcount; \
|
||||
volatile char *virt;
|
||||
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I915_VERBOSE) \
|
||||
DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \
|
||||
(n), __FUNCTION__); \
|
||||
if (dev_priv->ring.space < (n)*4) \
|
||||
i915_wait_ring(dev, (n)*4, __FUNCTION__); \
|
||||
outcount = 0; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
virt = dev_priv->ring.virtual_start; \
|
||||
} while (0)
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
|
||||
*(volatile unsigned int *)(virt + outring) = (n); \
|
||||
outcount++; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_LP_RING() do { \
|
||||
if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \
|
||||
dev_priv->ring.tail = outring; \
|
||||
dev_priv->ring.space -= outcount * 4; \
|
||||
I915_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
} while(0)
|
||||
|
||||
extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
|
||||
|
||||
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
|
||||
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
|
||||
#define CMD_REPORT_HEAD (7<<23)
|
||||
#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1)
|
||||
#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1)
|
||||
|
||||
#define INST_PARSER_CLIENT 0x00000000
|
||||
#define INST_OP_FLUSH 0x02000000
|
||||
#define INST_FLUSH_MAP_CACHE 0x00000001
|
||||
|
||||
#define BB1_START_ADDR_MASK (~0x7)
|
||||
#define BB1_PROTECTED (1<<0)
|
||||
#define BB1_UNPROTECTED (0<<0)
|
||||
#define BB2_END_ADDR_MASK (~0x7)
|
||||
|
||||
#define I915REG_HWSTAM 0x02098
|
||||
#define I915REG_INT_IDENTITY_R 0x020a4
|
||||
#define I915REG_INT_MASK_R 0x020a8
|
||||
#define I915REG_INT_ENABLE_R 0x020a0
|
||||
|
||||
#define SRX_INDEX 0x3c4
|
||||
#define SRX_DATA 0x3c5
|
||||
#define SR01 1
|
||||
#define SR01_SCREEN_OFF (1<<5)
|
||||
|
||||
#define PPCR 0x61204
|
||||
#define PPCR_ON (1<<0)
|
||||
|
||||
#define DVOB 0x61140
|
||||
#define DVOB_ON (1<<31)
|
||||
#define DVOC 0x61160
|
||||
#define DVOC_ON (1<<31)
|
||||
#define LVDS 0x61180
|
||||
#define LVDS_ON (1<<31)
|
||||
|
||||
#define ADPA 0x61100
|
||||
#define ADPA_DPMS_MASK (~(3<<10))
|
||||
#define ADPA_DPMS_ON (0<<10)
|
||||
#define ADPA_DPMS_SUSPEND (1<<10)
|
||||
#define ADPA_DPMS_STANDBY (2<<10)
|
||||
#define ADPA_DPMS_OFF (3<<10)
|
||||
|
||||
#define NOPID 0x2094
|
||||
#define LP_RING 0x2030
|
||||
#define HP_RING 0x2040
|
||||
#define RING_TAIL 0x00
|
||||
#define TAIL_ADDR 0x001FFFF8
|
||||
#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 0x0xFFFFF000
|
||||
#define RING_LEN 0x0C
|
||||
#define RING_NR_PAGES 0x001FF000
|
||||
#define RING_REPORT_MASK 0x00000006
|
||||
#define RING_REPORT_64K 0x00000002
|
||||
#define RING_REPORT_128K 0x00000004
|
||||
#define RING_NO_REPORT 0x00000000
|
||||
#define RING_VALID_MASK 0x00000001
|
||||
#define RING_VALID 0x00000001
|
||||
#define RING_INVALID 0x00000000
|
||||
|
||||
#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19))
|
||||
#define SC_UPDATE_SCISSOR (0x1<<1)
|
||||
#define SC_ENABLE_MASK (0x1<<0)
|
||||
#define SC_ENABLE (0x1<<0)
|
||||
|
||||
#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
|
||||
#define SCI_YMIN_MASK (0xffff<<16)
|
||||
#define SCI_XMIN_MASK (0xffff<<0)
|
||||
#define SCI_YMAX_MASK (0xffff<<16)
|
||||
#define SCI_XMAX_MASK (0xffff<<0)
|
||||
|
||||
#define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19))
|
||||
#define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
|
||||
#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
|
||||
#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
|
||||
#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4)
|
||||
#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
|
||||
#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
|
||||
|
||||
#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
|
||||
|
||||
#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)
|
||||
|
||||
#define MI_WAIT_FOR_EVENT ((0x3<<23))
|
||||
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
|
||||
#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
|
||||
|
||||
#define MI_LOAD_SCAN_LINES_INCL ((0x12<<23))
|
||||
|
||||
#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
|
||||
#define ASYNC_FLIP (1<<22)
|
||||
|
||||
#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
|
||||
|
||||
#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])
|
||||
|
||||
#endif
|
|
@ -0,0 +1,296 @@
|
|||
/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/i915_irq.c,v 1.4 2006/09/07 23:04:47 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include <dev/drm/drmP.h>
|
||||
#include <dev/drm/drm.h>
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
#define USER_INT_FLAG (1<<1)
|
||||
#define VSYNC_PIPEB_FLAG (1<<5)
|
||||
#define VSYNC_PIPEA_FLAG (1<<7)
|
||||
|
||||
#define MAX_NOPID ((u32)~0)
|
||||
|
||||
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *) arg;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u16 temp;
|
||||
|
||||
temp = I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
|
||||
temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
|
||||
|
||||
/*
|
||||
DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, (int)temp);
|
||||
*/
|
||||
|
||||
if (temp == 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
|
||||
|
||||
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
|
||||
if (temp & USER_INT_FLAG)
|
||||
DRM_WAKEUP(&dev_priv->irq_queue);
|
||||
|
||||
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int i915_emit_irq(drm_device_t * dev)
|
||||
{
|
||||
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
|
||||
|
||||
if (dev_priv->counter > 0x7FFFFFFFUL)
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
|
||||
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
OUT_RING(20);
|
||||
OUT_RING(dev_priv->counter);
|
||||
|
||||
OUT_RING(0);
|
||||
OUT_RING(0);
|
||||
OUT_RING(GFX_OP_USER_INTERRUPT);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
return dev_priv->counter;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int i915_wait_irq(drm_device_t * dev, int irq_nr)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
|
||||
(int)READ_BREADCRUMB(dev_priv));
|
||||
|
||||
if (READ_BREADCRUMB(dev_priv) >= irq_nr)
|
||||
return 0;
|
||||
|
||||
dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
|
||||
DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
|
||||
READ_BREADCRUMB(dev_priv) >= irq_nr);
|
||||
|
||||
if (ret == DRM_ERR(EBUSY)) {
|
||||
DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
|
||||
__FUNCTION__,
|
||||
(int)READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
|
||||
}
|
||||
|
||||
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1<<23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Needs the lock as it touches the ring.
|
||||
*/
|
||||
int i915_irq_emit(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_irq_emit_t emit;
|
||||
int result;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
|
||||
sizeof(emit));
|
||||
|
||||
result = i915_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 i915_irq_wait(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_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_i915_irq_wait_t __user *) data,
|
||||
sizeof(irqwait));
|
||||
|
||||
return i915_wait_irq(dev, irqwait.irq_seq);
|
||||
}
|
||||
|
||||
static int i915_enable_interrupt (drm_device_t *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u16 flag;
|
||||
|
||||
flag = 0;
|
||||
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
|
||||
flag |= VSYNC_PIPEA_FLAG;
|
||||
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
|
||||
flag |= VSYNC_PIPEB_FLAG;
|
||||
if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
|
||||
DRM_ERROR("%s called with invalid pipe 0x%x\n",
|
||||
__FUNCTION__, dev_priv->vblank_pipe);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the vblank monitor pipe
|
||||
*/
|
||||
int i915_vblank_pipe_set(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_pipe_t pipe;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data,
|
||||
sizeof(pipe));
|
||||
|
||||
dev_priv->vblank_pipe = pipe.pipe;
|
||||
return i915_enable_interrupt (dev);
|
||||
}
|
||||
|
||||
int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_pipe_t pipe;
|
||||
u16 flag;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
flag = I915_READ(I915REG_INT_ENABLE_R);
|
||||
pipe.pipe = 0;
|
||||
if (flag & VSYNC_PIPEA_FLAG)
|
||||
pipe.pipe |= DRM_I915_VBLANK_PIPE_A;
|
||||
if (flag & VSYNC_PIPEB_FLAG)
|
||||
pipe.pipe |= DRM_I915_VBLANK_PIPE_B;
|
||||
DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe,
|
||||
sizeof(pipe));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void i915_driver_irq_preinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
I915_WRITE16(I915REG_HWSTAM, 0xfffe);
|
||||
I915_WRITE16(I915REG_INT_MASK_R, 0x0);
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
|
||||
}
|
||||
|
||||
void i915_driver_irq_postinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
i915_enable_interrupt(dev);
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
|
||||
}
|
||||
|
||||
void i915_driver_irq_uninstall(drm_device_t * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u16 temp;
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
I915_WRITE16(I915REG_HWSTAM, 0xffff);
|
||||
I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
|
||||
|
||||
temp = I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
|
||||
}
|
|
@ -0,0 +1,402 @@
|
|||
/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/i915_mem.c,v 1.3 2006/04/09 20:45:45 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include <dev/drm/drmP.h>
|
||||
#include <dev/drm/drm.h>
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
/* This memory manager is integrated into the global/local lru
|
||||
* mechanisms used by the clients. Specifically, it operates by
|
||||
* setting the 'in_use' fields of the global LRU to indicate whether
|
||||
* this region is privately allocated to a client.
|
||||
*
|
||||
* This does require the client to actually respect that field.
|
||||
*
|
||||
* Currently no effort is made to allocate 'private' memory in any
|
||||
* clever way - the LRU information isn't used to determine which
|
||||
* block to allocate, and the ring is drained prior to allocations --
|
||||
* in other words allocation is expensive.
|
||||
*/
|
||||
static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_tex_region_t *list;
|
||||
unsigned shift, nr;
|
||||
unsigned start;
|
||||
unsigned end;
|
||||
unsigned i;
|
||||
int age;
|
||||
|
||||
shift = dev_priv->tex_lru_log_granularity;
|
||||
nr = I915_NR_TEX_REGIONS;
|
||||
|
||||
start = p->start >> shift;
|
||||
end = (p->start + p->size - 1) >> shift;
|
||||
|
||||
age = ++sarea_priv->texAge;
|
||||
list = sarea_priv->texList;
|
||||
|
||||
/* Mark the regions with the new flag and update their age. Move
|
||||
* them to head of list to preserve LRU semantics.
|
||||
*/
|
||||
for (i = start; i <= end; i++) {
|
||||
list[i].in_use = in_use;
|
||||
list[i].age = age;
|
||||
|
||||
/* remove_from_list(i)
|
||||
*/
|
||||
list[(unsigned)list[i].next].prev = list[i].prev;
|
||||
list[(unsigned)list[i].prev].next = list[i].next;
|
||||
|
||||
/* insert_at_head(list, i)
|
||||
*/
|
||||
list[i].prev = nr;
|
||||
list[i].next = list[nr].next;
|
||||
list[(unsigned)list[nr].next].prev = i;
|
||||
list[nr].next = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
DRMFILE filp)
|
||||
{
|
||||
/* Maybe cut off the start of an existing block */
|
||||
if (start > p->start) {
|
||||
struct mem_block *newblock =
|
||||
drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
|
||||
if (!newblock)
|
||||
goto out;
|
||||
newblock->start = start;
|
||||
newblock->size = p->size - (start - p->start);
|
||||
newblock->filp = NULL;
|
||||
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_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
|
||||
if (!newblock)
|
||||
goto out;
|
||||
newblock->start = start + size;
|
||||
newblock->size = p->size - size;
|
||||
newblock->filp = NULL;
|
||||
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->filp = filp;
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct mem_block *alloc_block(struct mem_block *heap, int size,
|
||||
int align2, DRMFILE filp)
|
||||
{
|
||||
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->filp == NULL && start + size <= p->start + p->size)
|
||||
return split_block(p, start, size, filp);
|
||||
}
|
||||
|
||||
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->filp = NULL;
|
||||
|
||||
/* Assumes a single contiguous range. Needs a special filp in
|
||||
* 'heap' to stop it being subsumed.
|
||||
*/
|
||||
if (p->next->filp == NULL) {
|
||||
struct mem_block *q = p->next;
|
||||
p->size += q->size;
|
||||
p->next = q->next;
|
||||
p->next->prev = p;
|
||||
drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
|
||||
}
|
||||
|
||||
if (p->prev->filp == NULL) {
|
||||
struct mem_block *q = p->prev;
|
||||
q->size += p->size;
|
||||
q->next = p->next;
|
||||
q->next->prev = q;
|
||||
drm_free(p, sizeof(*q), DRM_MEM_BUFLISTS);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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_alloc(sizeof(*blocks), DRM_MEM_BUFLISTS);
|
||||
|
||||
if (!blocks)
|
||||
return -ENOMEM;
|
||||
|
||||
*heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFLISTS);
|
||||
if (!*heap) {
|
||||
drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFLISTS);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
blocks->start = start;
|
||||
blocks->size = size;
|
||||
blocks->filp = NULL;
|
||||
blocks->next = blocks->prev = *heap;
|
||||
|
||||
memset(*heap, 0, sizeof(**heap));
|
||||
(*heap)->filp = (DRMFILE) - 1;
|
||||
(*heap)->next = (*heap)->prev = blocks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free all blocks associated with the releasing file.
|
||||
*/
|
||||
void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
if (!heap || !heap->next)
|
||||
return;
|
||||
|
||||
for (p = heap->next; p != heap; p = p->next) {
|
||||
if (p->filp == filp) {
|
||||
p->filp = NULL;
|
||||
mark_block(dev, p, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assumes a single contiguous range. Needs a special filp in
|
||||
* 'heap' to stop it being subsumed.
|
||||
*/
|
||||
for (p = heap->next; p != heap; p = p->next) {
|
||||
while (p->filp == NULL && p->next->filp == NULL) {
|
||||
struct mem_block *q = p->next;
|
||||
p->size += q->size;
|
||||
p->next = q->next;
|
||||
p->next->prev = p;
|
||||
drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Shutdown.
|
||||
*/
|
||||
void i915_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, sizeof(*q), DRM_MEM_BUFLISTS);
|
||||
}
|
||||
|
||||
drm_free(*heap, sizeof(**heap), DRM_MEM_BUFLISTS);
|
||||
*heap = NULL;
|
||||
}
|
||||
|
||||
static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
|
||||
{
|
||||
switch (region) {
|
||||
case I915_MEM_REGION_AGP:
|
||||
return &dev_priv->agp_heap;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* IOCTL HANDLERS */
|
||||
|
||||
int i915_mem_alloc(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_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_i915_mem_alloc_t __user *) 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, filp);
|
||||
|
||||
if (!block)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
mark_block(dev, block, 1);
|
||||
|
||||
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 i915_mem_free(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_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_i915_mem_free_t __user *) 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->filp != filp)
|
||||
return DRM_ERR(EPERM);
|
||||
|
||||
mark_block(dev, block, 0);
|
||||
free_block(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i915_mem_init_heap(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_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_i915_mem_init_heap_t __user *) 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);
|
||||
}
|
||||
|
||||
int i915_mem_destroy_heap( DRM_IOCTL_ARGS )
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_mem_destroy_heap_t destroyheap;
|
||||
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( destroyheap, (drm_i915_mem_destroy_heap_t *)data,
|
||||
sizeof(destroyheap) );
|
||||
|
||||
heap = get_heap( dev_priv, destroyheap.region );
|
||||
if (!heap) {
|
||||
DRM_ERROR("get_heap failed");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
if (!*heap) {
|
||||
DRM_ERROR("heap not initialized?");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
i915_mem_takedown( heap );
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,261 @@
|
|||
/* mach64_drm.h -- Public header for the mach64 driver -*- linux-c -*-
|
||||
* Created: Thu Nov 30 20:04:32 2000 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 Gareth Hughes
|
||||
* Copyright 2002 Frank C. Earl
|
||||
* Copyright 2002-2003 Leif Delgass
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* THE COPYRIGHT OWNER(S) 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Frank C. Earl <fearl@airmail.net>
|
||||
* Leif Delgass <ldelgass@retinalburn.net>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mach64_drm.h,v 1.3 2006/09/07 23:04:47 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __MACH64_DRM_H__
|
||||
#define __MACH64_DRM_H__
|
||||
|
||||
/* WARNING: If you change any of these defines, make sure to change the
|
||||
* defines in the Xserver file (mach64_sarea.h)
|
||||
*/
|
||||
#ifndef __MACH64_SAREA_DEFINES__
|
||||
#define __MACH64_SAREA_DEFINES__
|
||||
|
||||
/* What needs to be changed for the current vertex buffer?
|
||||
* GH: We're going to be pedantic about this. We want the card to do as
|
||||
* little as possible, so let's avoid having it fetch a whole bunch of
|
||||
* register values that don't change all that often, if at all.
|
||||
*/
|
||||
#define MACH64_UPLOAD_DST_OFF_PITCH 0x0001
|
||||
#define MACH64_UPLOAD_Z_OFF_PITCH 0x0002
|
||||
#define MACH64_UPLOAD_Z_ALPHA_CNTL 0x0004
|
||||
#define MACH64_UPLOAD_SCALE_3D_CNTL 0x0008
|
||||
#define MACH64_UPLOAD_DP_FOG_CLR 0x0010
|
||||
#define MACH64_UPLOAD_DP_WRITE_MASK 0x0020
|
||||
#define MACH64_UPLOAD_DP_PIX_WIDTH 0x0040
|
||||
#define MACH64_UPLOAD_SETUP_CNTL 0x0080
|
||||
#define MACH64_UPLOAD_MISC 0x0100
|
||||
#define MACH64_UPLOAD_TEXTURE 0x0200
|
||||
#define MACH64_UPLOAD_TEX0IMAGE 0x0400
|
||||
#define MACH64_UPLOAD_TEX1IMAGE 0x0800
|
||||
#define MACH64_UPLOAD_CLIPRECTS 0x1000 /* handled client-side */
|
||||
#define MACH64_UPLOAD_CONTEXT 0x00ff
|
||||
#define MACH64_UPLOAD_ALL 0x1fff
|
||||
|
||||
/* DMA buffer size
|
||||
*/
|
||||
#define MACH64_BUFFER_SIZE 16384
|
||||
|
||||
/* Max number of swaps allowed on the ring
|
||||
* before the client must wait
|
||||
*/
|
||||
#define MACH64_MAX_QUEUED_FRAMES 3U
|
||||
|
||||
/* Byte offsets for host blit buffer data
|
||||
*/
|
||||
#define MACH64_HOSTDATA_BLIT_OFFSET 104
|
||||
|
||||
/* Keep these small for testing.
|
||||
*/
|
||||
#define MACH64_NR_SAREA_CLIPRECTS 8
|
||||
|
||||
#define MACH64_CARD_HEAP 0
|
||||
#define MACH64_AGP_HEAP 1
|
||||
#define MACH64_NR_TEX_HEAPS 2
|
||||
#define MACH64_NR_TEX_REGIONS 64
|
||||
#define MACH64_LOG_TEX_GRANULARITY 16
|
||||
|
||||
#define MACH64_TEX_MAXLEVELS 1
|
||||
|
||||
#define MACH64_NR_CONTEXT_REGS 15
|
||||
#define MACH64_NR_TEXTURE_REGS 4
|
||||
|
||||
#endif /* __MACH64_SAREA_DEFINES__ */
|
||||
|
||||
typedef struct {
|
||||
unsigned int dst_off_pitch;
|
||||
|
||||
unsigned int z_off_pitch;
|
||||
unsigned int z_cntl;
|
||||
unsigned int alpha_tst_cntl;
|
||||
|
||||
unsigned int scale_3d_cntl;
|
||||
|
||||
unsigned int sc_left_right;
|
||||
unsigned int sc_top_bottom;
|
||||
|
||||
unsigned int dp_fog_clr;
|
||||
unsigned int dp_write_mask;
|
||||
unsigned int dp_pix_width;
|
||||
unsigned int dp_mix;
|
||||
unsigned int dp_src;
|
||||
|
||||
unsigned int clr_cmp_cntl;
|
||||
unsigned int gui_traj_cntl;
|
||||
|
||||
unsigned int setup_cntl;
|
||||
|
||||
unsigned int tex_size_pitch;
|
||||
unsigned int tex_cntl;
|
||||
unsigned int secondary_tex_off;
|
||||
unsigned int tex_offset;
|
||||
} drm_mach64_context_regs_t;
|
||||
|
||||
typedef struct drm_mach64_sarea {
|
||||
/* The channel for communication of state information to the kernel
|
||||
* on firing a vertex dma buffer.
|
||||
*/
|
||||
drm_mach64_context_regs_t context_state;
|
||||
unsigned int dirty;
|
||||
unsigned int vertsize;
|
||||
|
||||
/* The current cliprects, or a subset thereof.
|
||||
*/
|
||||
drm_clip_rect_t boxes[MACH64_NR_SAREA_CLIPRECTS];
|
||||
unsigned int nbox;
|
||||
|
||||
/* Counters for client-side throttling of rendering clients.
|
||||
*/
|
||||
unsigned int frames_queued;
|
||||
|
||||
/* Texture memory LRU.
|
||||
*/
|
||||
drm_tex_region_t tex_list[MACH64_NR_TEX_HEAPS][MACH64_NR_TEX_REGIONS +
|
||||
1];
|
||||
unsigned int tex_age[MACH64_NR_TEX_HEAPS];
|
||||
int ctx_owner;
|
||||
} drm_mach64_sarea_t;
|
||||
|
||||
/* WARNING: If you change any of these defines, make sure to change the
|
||||
* defines in the Xserver file (mach64_common.h)
|
||||
*/
|
||||
|
||||
/* Mach64 specific ioctls
|
||||
* The device specific ioctl range is 0x40 to 0x79.
|
||||
*/
|
||||
|
||||
#define DRM_MACH64_INIT 0x00
|
||||
#define DRM_MACH64_IDLE 0x01
|
||||
#define DRM_MACH64_RESET 0x02
|
||||
#define DRM_MACH64_SWAP 0x03
|
||||
#define DRM_MACH64_CLEAR 0x04
|
||||
#define DRM_MACH64_VERTEX 0x05
|
||||
#define DRM_MACH64_BLIT 0x06
|
||||
#define DRM_MACH64_FLUSH 0x07
|
||||
#define DRM_MACH64_GETPARAM 0x08
|
||||
|
||||
#define DRM_IOCTL_MACH64_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_INIT, drm_mach64_init_t)
|
||||
#define DRM_IOCTL_MACH64_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_IDLE )
|
||||
#define DRM_IOCTL_MACH64_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_RESET )
|
||||
#define DRM_IOCTL_MACH64_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_SWAP )
|
||||
#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_CLEAR, drm_mach64_clear_t)
|
||||
#define DRM_IOCTL_MACH64_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_VERTEX, drm_mach64_vertex_t)
|
||||
#define DRM_IOCTL_MACH64_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MACH64_BLIT, drm_mach64_blit_t)
|
||||
#define DRM_IOCTL_MACH64_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_MACH64_FLUSH )
|
||||
#define DRM_IOCTL_MACH64_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_MACH64_GETPARAM, drm_mach64_getparam_t)
|
||||
|
||||
/* Buffer flags for clears
|
||||
*/
|
||||
#define MACH64_FRONT 0x1
|
||||
#define MACH64_BACK 0x2
|
||||
#define MACH64_DEPTH 0x4
|
||||
|
||||
/* Primitive types for vertex buffers
|
||||
*/
|
||||
#define MACH64_PRIM_POINTS 0x00000000
|
||||
#define MACH64_PRIM_LINES 0x00000001
|
||||
#define MACH64_PRIM_LINE_LOOP 0x00000002
|
||||
#define MACH64_PRIM_LINE_STRIP 0x00000003
|
||||
#define MACH64_PRIM_TRIANGLES 0x00000004
|
||||
#define MACH64_PRIM_TRIANGLE_STRIP 0x00000005
|
||||
#define MACH64_PRIM_TRIANGLE_FAN 0x00000006
|
||||
#define MACH64_PRIM_QUADS 0x00000007
|
||||
#define MACH64_PRIM_QUAD_STRIP 0x00000008
|
||||
#define MACH64_PRIM_POLYGON 0x00000009
|
||||
|
||||
typedef enum _drm_mach64_dma_mode_t {
|
||||
MACH64_MODE_DMA_ASYNC,
|
||||
MACH64_MODE_DMA_SYNC,
|
||||
MACH64_MODE_MMIO
|
||||
} drm_mach64_dma_mode_t;
|
||||
|
||||
typedef struct drm_mach64_init {
|
||||
enum {
|
||||
DRM_MACH64_INIT_DMA = 0x01,
|
||||
DRM_MACH64_CLEANUP_DMA = 0x02
|
||||
} func;
|
||||
|
||||
unsigned long sarea_priv_offset;
|
||||
int is_pci;
|
||||
drm_mach64_dma_mode_t dma_mode;
|
||||
|
||||
unsigned int fb_bpp;
|
||||
unsigned int front_offset, front_pitch;
|
||||
unsigned int back_offset, back_pitch;
|
||||
|
||||
unsigned int depth_bpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
|
||||
unsigned long fb_offset;
|
||||
unsigned long mmio_offset;
|
||||
unsigned long ring_offset;
|
||||
unsigned long buffers_offset;
|
||||
unsigned long agp_textures_offset;
|
||||
} drm_mach64_init_t;
|
||||
|
||||
typedef struct drm_mach64_clear {
|
||||
unsigned int flags;
|
||||
int x, y, w, h;
|
||||
unsigned int clear_color;
|
||||
unsigned int clear_depth;
|
||||
} drm_mach64_clear_t;
|
||||
|
||||
typedef struct drm_mach64_vertex {
|
||||
int prim;
|
||||
void *buf; /* Address of vertex buffer */
|
||||
unsigned long used; /* Number of bytes in buffer */
|
||||
int discard; /* Client finished with buffer? */
|
||||
} drm_mach64_vertex_t;
|
||||
|
||||
typedef struct drm_mach64_blit {
|
||||
int idx;
|
||||
int pitch;
|
||||
int offset;
|
||||
int format;
|
||||
unsigned short x, y;
|
||||
unsigned short width, height;
|
||||
} drm_mach64_blit_t;
|
||||
|
||||
typedef struct drm_mach64_getparam {
|
||||
enum {
|
||||
MACH64_PARAM_FRAMES_QUEUED = 0x01,
|
||||
MACH64_PARAM_IRQ_NR = 0x02
|
||||
} param;
|
||||
void *value;
|
||||
} drm_mach64_getparam_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,142 @@
|
|||
/* mach64_drv.c -- ATI Rage 128 driver -*- linux-c -*-
|
||||
* Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mach64_drv.c,v 1.3 2005/12/20 22:44:36 jhb Exp $");
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mach64_drm.h"
|
||||
#include "mach64_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t mach64_pciidlist[] = {
|
||||
mach64_PCI_IDS
|
||||
};
|
||||
|
||||
static void mach64_configure(drm_device_t *dev)
|
||||
{
|
||||
dev->driver.buf_priv_size = 1; /* No dev_priv */
|
||||
dev->driver.lastclose = mach64_driver_lastclose;
|
||||
dev->driver.vblank_wait = mach64_driver_vblank_wait;
|
||||
dev->driver.irq_preinstall = mach64_driver_irq_preinstall;
|
||||
dev->driver.irq_postinstall = mach64_driver_irq_postinstall;
|
||||
dev->driver.irq_uninstall = mach64_driver_irq_uninstall;
|
||||
dev->driver.irq_handler = mach64_driver_irq_handler;
|
||||
dev->driver.dma_ioctl = mach64_dma_buffers;
|
||||
|
||||
dev->driver.ioctls = mach64_ioctls;
|
||||
dev->driver.max_ioctl = mach64_max_ioctl;
|
||||
|
||||
dev->driver.name = DRIVER_NAME;
|
||||
dev->driver.desc = DRIVER_DESC;
|
||||
dev->driver.date = DRIVER_DATE;
|
||||
dev->driver.major = DRIVER_MAJOR;
|
||||
dev->driver.minor = DRIVER_MINOR;
|
||||
dev->driver.patchlevel = DRIVER_PATCHLEVEL;
|
||||
|
||||
dev->driver.use_agp = 1;
|
||||
dev->driver.use_mtrr = 1;
|
||||
dev->driver.use_pci_dma = 1;
|
||||
dev->driver.use_dma = 1;
|
||||
dev->driver.use_irq = 1;
|
||||
dev->driver.use_vbl_irq = 1;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
mach64_probe(device_t dev)
|
||||
{
|
||||
return drm_probe(dev, mach64_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
mach64_attach(device_t nbdev)
|
||||
{
|
||||
drm_device_t *dev = device_get_softc(nbdev);
|
||||
|
||||
bzero(dev, sizeof(drm_device_t));
|
||||
mach64_configure(dev);
|
||||
return drm_attach(nbdev, mach64_pciidlist);
|
||||
}
|
||||
|
||||
static device_method_t mach64_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, mach64_probe),
|
||||
DEVMETHOD(device_attach, mach64_attach),
|
||||
DEVMETHOD(device_detach, drm_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t mach64_driver = {
|
||||
"drm",
|
||||
mach64_methods,
|
||||
sizeof(drm_device_t)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(mach64, vgapci, mach64_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(mach64, pci, mach64_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(mach64, drm, 1, 1, 1);
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
static int
|
||||
mach64drm_probe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
return drm_probe(pa, mach64_pciidlist);
|
||||
}
|
||||
|
||||
static void
|
||||
mach64drm_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
drm_device_t *dev = (drm_device_t *)self;
|
||||
|
||||
mach64_configure(dev);
|
||||
return drm_attach(self, pa, mach64_pciidlist);
|
||||
}
|
||||
|
||||
CFATTACH_DECL(mach64drm, sizeof(drm_device_t), mach64drm_probe, mach64drm_attach,
|
||||
drm_detach, drm_activate);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,141 @@
|
|||
/* mach64_irq.c -- IRQ handling for ATI Mach64 -*- linux-c -*-
|
||||
* Created: Tue Feb 25, 2003 by Leif Delgass, based on radeon_irq.c/r128_irq.c
|
||||
*/
|
||||
/*-
|
||||
* Copyright (C) The Weather Channel, Inc. 2002.
|
||||
* Copyright 2003 Leif Delgass
|
||||
* 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
|
||||
* THE COPYRIGHT OWNER(S) 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>
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
* Leif Delgass <ldelgass@retinalburn.net>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mach64_irq.c,v 1.2 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mach64_drm.h"
|
||||
#include "mach64_drv.h"
|
||||
|
||||
irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *) arg;
|
||||
drm_mach64_private_t *dev_priv =
|
||||
(drm_mach64_private_t *) dev->dev_private;
|
||||
int status;
|
||||
|
||||
status = MACH64_READ(MACH64_CRTC_INT_CNTL);
|
||||
|
||||
/* VBLANK interrupt */
|
||||
if (status & MACH64_CRTC_VBLANK_INT) {
|
||||
/* Mask off all interrupt ack bits before setting the ack bit, since
|
||||
* there may be other handlers outside the DRM.
|
||||
*
|
||||
* NOTE: On mach64, you need to keep the enable bits set when doing
|
||||
* the ack, despite what the docs say about not acking and enabling
|
||||
* in a single write.
|
||||
*/
|
||||
MACH64_WRITE(MACH64_CRTC_INT_CNTL,
|
||||
(status & ~MACH64_CRTC_INT_ACKS)
|
||||
| MACH64_CRTC_VBLANK_INT);
|
||||
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int mach64_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
|
||||
{
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void mach64_driver_irq_preinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv =
|
||||
(drm_mach64_private_t *) dev->dev_private;
|
||||
|
||||
u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL);
|
||||
|
||||
DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status);
|
||||
|
||||
/* Disable and clear VBLANK interrupt */
|
||||
MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN)
|
||||
| MACH64_CRTC_VBLANK_INT);
|
||||
}
|
||||
|
||||
void mach64_driver_irq_postinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv =
|
||||
(drm_mach64_private_t *) dev->dev_private;
|
||||
|
||||
/* Turn on VBLANK interrupt */
|
||||
MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL)
|
||||
| MACH64_CRTC_VBLANK_INT_EN);
|
||||
|
||||
DRM_DEBUG("after install CRTC_INT_CTNL: 0x%08x\n",
|
||||
MACH64_READ(MACH64_CRTC_INT_CNTL));
|
||||
|
||||
}
|
||||
|
||||
void mach64_driver_irq_uninstall(drm_device_t * dev)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv =
|
||||
(drm_mach64_private_t *) dev->dev_private;
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
/* Disable and clear VBLANK interrupt */
|
||||
MACH64_WRITE(MACH64_CRTC_INT_CNTL,
|
||||
(MACH64_READ(MACH64_CRTC_INT_CNTL) &
|
||||
~MACH64_CRTC_VBLANK_INT_EN)
|
||||
| MACH64_CRTC_VBLANK_INT);
|
||||
|
||||
DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n",
|
||||
MACH64_READ(MACH64_CRTC_INT_CNTL));
|
||||
}
|
|
@ -0,0 +1,923 @@
|
|||
/* mach64_state.c -- State support for mach64 (Rage Pro) driver -*- linux-c -*-
|
||||
* Created: Sun Dec 03 19:20:26 2000 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 Gareth Hughes
|
||||
* Copyright 2002-2003 Leif Delgass
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* THE COPYRIGHT OWNER(S) 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Leif Delgass <ldelgass@retinalburn.net>
|
||||
* Jos<EFBFBD>Fonseca <j_r_fonseca@yahoo.co.uk>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mach64_state.c,v 1.2 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mach64_drm.h"
|
||||
#include "mach64_drv.h"
|
||||
|
||||
/* Interface history:
|
||||
*
|
||||
* 1.0 - Initial mach64 DRM
|
||||
*
|
||||
*/
|
||||
drm_ioctl_desc_t mach64_ioctls[] = {
|
||||
[DRM_IOCTL_NR(DRM_MACH64_INIT)] = {mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_MACH64_CLEAR)] = {mach64_dma_clear, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_MACH64_SWAP)] = {mach64_dma_swap, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_MACH64_IDLE)] = {mach64_dma_idle, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_MACH64_RESET)] = {mach64_engine_reset, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_MACH64_VERTEX)] = {mach64_dma_vertex, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_MACH64_BLIT)] = {mach64_dma_blit, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_MACH64_FLUSH)] = {mach64_dma_flush, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_MACH64_GETPARAM)] = {mach64_get_param, DRM_AUTH},
|
||||
};
|
||||
|
||||
int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls);
|
||||
|
||||
/* ================================================================
|
||||
* DMA hardware state programming functions
|
||||
*/
|
||||
|
||||
static void mach64_print_dirty(const char *msg, unsigned int flags)
|
||||
{
|
||||
DRM_DEBUG("%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
msg,
|
||||
flags,
|
||||
(flags & MACH64_UPLOAD_DST_OFF_PITCH) ? "dst_off_pitch, " :
|
||||
"",
|
||||
(flags & MACH64_UPLOAD_Z_ALPHA_CNTL) ? "z_alpha_cntl, " : "",
|
||||
(flags & MACH64_UPLOAD_SCALE_3D_CNTL) ? "scale_3d_cntl, " :
|
||||
"", (flags & MACH64_UPLOAD_DP_FOG_CLR) ? "dp_fog_clr, " : "",
|
||||
(flags & MACH64_UPLOAD_DP_WRITE_MASK) ? "dp_write_mask, " :
|
||||
"",
|
||||
(flags & MACH64_UPLOAD_DP_PIX_WIDTH) ? "dp_pix_width, " : "",
|
||||
(flags & MACH64_UPLOAD_SETUP_CNTL) ? "setup_cntl, " : "",
|
||||
(flags & MACH64_UPLOAD_MISC) ? "misc, " : "",
|
||||
(flags & MACH64_UPLOAD_TEXTURE) ? "texture, " : "",
|
||||
(flags & MACH64_UPLOAD_TEX0IMAGE) ? "tex0 image, " : "",
|
||||
(flags & MACH64_UPLOAD_TEX1IMAGE) ? "tex1 image, " : "",
|
||||
(flags & MACH64_UPLOAD_CLIPRECTS) ? "cliprects, " : "");
|
||||
}
|
||||
|
||||
/* Mach64 doesn't have hardware cliprects, just one hardware scissor,
|
||||
* so the GL scissor is intersected with each cliprect here
|
||||
*/
|
||||
/* This function returns 0 on success, 1 for no intersection, and
|
||||
* negative for an error
|
||||
*/
|
||||
static int mach64_emit_cliprect(DRMFILE filp, drm_mach64_private_t * dev_priv,
|
||||
drm_clip_rect_t * box)
|
||||
{
|
||||
u32 sc_left_right, sc_top_bottom;
|
||||
drm_clip_rect_t scissor;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mach64_context_regs_t *regs = &sarea_priv->context_state;
|
||||
DMALOCALS;
|
||||
|
||||
DRM_DEBUG("%s: box=%p\n", __FUNCTION__, box);
|
||||
|
||||
/* Get GL scissor */
|
||||
/* FIXME: store scissor in SAREA as a cliprect instead of in
|
||||
* hardware format, or do intersection client-side
|
||||
*/
|
||||
scissor.x1 = regs->sc_left_right & 0xffff;
|
||||
scissor.x2 = (regs->sc_left_right & 0xffff0000) >> 16;
|
||||
scissor.y1 = regs->sc_top_bottom & 0xffff;
|
||||
scissor.y2 = (regs->sc_top_bottom & 0xffff0000) >> 16;
|
||||
|
||||
/* Intersect GL scissor with cliprect */
|
||||
if (box->x1 > scissor.x1)
|
||||
scissor.x1 = box->x1;
|
||||
if (box->y1 > scissor.y1)
|
||||
scissor.y1 = box->y1;
|
||||
if (box->x2 < scissor.x2)
|
||||
scissor.x2 = box->x2;
|
||||
if (box->y2 < scissor.y2)
|
||||
scissor.y2 = box->y2;
|
||||
/* positive return means skip */
|
||||
if (scissor.x1 >= scissor.x2)
|
||||
return 1;
|
||||
if (scissor.y1 >= scissor.y2)
|
||||
return 1;
|
||||
|
||||
DMAGETPTR(filp, dev_priv, 2); /* returns on failure to get buffer */
|
||||
|
||||
sc_left_right = ((scissor.x1 << 0) | (scissor.x2 << 16));
|
||||
sc_top_bottom = ((scissor.y1 << 0) | (scissor.y2 << 16));
|
||||
|
||||
DMAOUTREG(MACH64_SC_LEFT_RIGHT, sc_left_right);
|
||||
DMAOUTREG(MACH64_SC_TOP_BOTTOM, sc_top_bottom);
|
||||
|
||||
DMAADVANCE(dev_priv, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int mach64_emit_state(DRMFILE filp,
|
||||
drm_mach64_private_t * dev_priv)
|
||||
{
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mach64_context_regs_t *regs = &sarea_priv->context_state;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
u32 offset = ((regs->tex_size_pitch & 0xf0) >> 2);
|
||||
DMALOCALS;
|
||||
|
||||
if (MACH64_VERBOSE) {
|
||||
mach64_print_dirty(__FUNCTION__, dirty);
|
||||
} else {
|
||||
DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty);
|
||||
}
|
||||
|
||||
DMAGETPTR(filp, dev_priv, 17); /* returns on failure to get buffer */
|
||||
|
||||
if (dirty & MACH64_UPLOAD_MISC) {
|
||||
DMAOUTREG(MACH64_DP_MIX, regs->dp_mix);
|
||||
DMAOUTREG(MACH64_DP_SRC, regs->dp_src);
|
||||
DMAOUTREG(MACH64_CLR_CMP_CNTL, regs->clr_cmp_cntl);
|
||||
DMAOUTREG(MACH64_GUI_TRAJ_CNTL, regs->gui_traj_cntl);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_MISC;
|
||||
}
|
||||
|
||||
if (dirty & MACH64_UPLOAD_DST_OFF_PITCH) {
|
||||
DMAOUTREG(MACH64_DST_OFF_PITCH, regs->dst_off_pitch);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_DST_OFF_PITCH;
|
||||
}
|
||||
if (dirty & MACH64_UPLOAD_Z_OFF_PITCH) {
|
||||
DMAOUTREG(MACH64_Z_OFF_PITCH, regs->z_off_pitch);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_Z_OFF_PITCH;
|
||||
}
|
||||
if (dirty & MACH64_UPLOAD_Z_ALPHA_CNTL) {
|
||||
DMAOUTREG(MACH64_Z_CNTL, regs->z_cntl);
|
||||
DMAOUTREG(MACH64_ALPHA_TST_CNTL, regs->alpha_tst_cntl);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_Z_ALPHA_CNTL;
|
||||
}
|
||||
if (dirty & MACH64_UPLOAD_SCALE_3D_CNTL) {
|
||||
DMAOUTREG(MACH64_SCALE_3D_CNTL, regs->scale_3d_cntl);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_SCALE_3D_CNTL;
|
||||
}
|
||||
if (dirty & MACH64_UPLOAD_DP_FOG_CLR) {
|
||||
DMAOUTREG(MACH64_DP_FOG_CLR, regs->dp_fog_clr);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_DP_FOG_CLR;
|
||||
}
|
||||
if (dirty & MACH64_UPLOAD_DP_WRITE_MASK) {
|
||||
DMAOUTREG(MACH64_DP_WRITE_MASK, regs->dp_write_mask);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_DP_WRITE_MASK;
|
||||
}
|
||||
if (dirty & MACH64_UPLOAD_DP_PIX_WIDTH) {
|
||||
DMAOUTREG(MACH64_DP_PIX_WIDTH, regs->dp_pix_width);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_DP_PIX_WIDTH;
|
||||
}
|
||||
if (dirty & MACH64_UPLOAD_SETUP_CNTL) {
|
||||
DMAOUTREG(MACH64_SETUP_CNTL, regs->setup_cntl);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_SETUP_CNTL;
|
||||
}
|
||||
|
||||
if (dirty & MACH64_UPLOAD_TEXTURE) {
|
||||
DMAOUTREG(MACH64_TEX_SIZE_PITCH, regs->tex_size_pitch);
|
||||
DMAOUTREG(MACH64_TEX_CNTL, regs->tex_cntl);
|
||||
DMAOUTREG(MACH64_SECONDARY_TEX_OFF, regs->secondary_tex_off);
|
||||
DMAOUTREG(MACH64_TEX_0_OFF + offset, regs->tex_offset);
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_TEXTURE;
|
||||
}
|
||||
|
||||
DMAADVANCE(dev_priv, 1);
|
||||
|
||||
sarea_priv->dirty &= MACH64_UPLOAD_CLIPRECTS;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* DMA command dispatch functions
|
||||
*/
|
||||
|
||||
static int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev,
|
||||
unsigned int flags,
|
||||
int cx, int cy, int cw, int ch,
|
||||
unsigned int clear_color,
|
||||
unsigned int clear_depth)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mach64_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
int nbox = sarea_priv->nbox;
|
||||
drm_clip_rect_t *pbox = sarea_priv->boxes;
|
||||
u32 fb_bpp, depth_bpp;
|
||||
int i;
|
||||
DMALOCALS;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
switch (dev_priv->fb_bpp) {
|
||||
case 16:
|
||||
fb_bpp = MACH64_DATATYPE_RGB565;
|
||||
break;
|
||||
case 32:
|
||||
fb_bpp = MACH64_DATATYPE_ARGB8888;
|
||||
break;
|
||||
default:
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
switch (dev_priv->depth_bpp) {
|
||||
case 16:
|
||||
depth_bpp = MACH64_DATATYPE_RGB565;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
depth_bpp = MACH64_DATATYPE_ARGB8888;
|
||||
break;
|
||||
default:
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (!nbox)
|
||||
return 0;
|
||||
|
||||
DMAGETPTR(filp, dev_priv, nbox * 31); /* returns on failure to get buffer */
|
||||
|
||||
for (i = 0; i < nbox; i++) {
|
||||
int x = pbox[i].x1;
|
||||
int y = pbox[i].y1;
|
||||
int w = pbox[i].x2 - x;
|
||||
int h = pbox[i].y2 - y;
|
||||
|
||||
DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
|
||||
pbox[i].x1, pbox[i].y1,
|
||||
pbox[i].x2, pbox[i].y2, flags);
|
||||
|
||||
if (flags & (MACH64_FRONT | MACH64_BACK)) {
|
||||
/* Setup for color buffer clears
|
||||
*/
|
||||
|
||||
DMAOUTREG(MACH64_Z_CNTL, 0);
|
||||
DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
|
||||
|
||||
DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right);
|
||||
DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom);
|
||||
|
||||
DMAOUTREG(MACH64_CLR_CMP_CNTL, 0);
|
||||
DMAOUTREG(MACH64_GUI_TRAJ_CNTL,
|
||||
(MACH64_DST_X_LEFT_TO_RIGHT |
|
||||
MACH64_DST_Y_TOP_TO_BOTTOM));
|
||||
|
||||
DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) |
|
||||
(fb_bpp << 4) |
|
||||
(fb_bpp << 8) |
|
||||
(fb_bpp << 16) |
|
||||
(fb_bpp << 28)));
|
||||
|
||||
DMAOUTREG(MACH64_DP_FRGD_CLR, clear_color);
|
||||
DMAOUTREG(MACH64_DP_WRITE_MASK, ctx->dp_write_mask);
|
||||
DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D |
|
||||
MACH64_FRGD_MIX_S));
|
||||
DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR |
|
||||
MACH64_FRGD_SRC_FRGD_CLR |
|
||||
MACH64_MONO_SRC_ONE));
|
||||
|
||||
}
|
||||
|
||||
if (flags & MACH64_FRONT) {
|
||||
|
||||
DMAOUTREG(MACH64_DST_OFF_PITCH,
|
||||
dev_priv->front_offset_pitch);
|
||||
DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x);
|
||||
DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w);
|
||||
|
||||
}
|
||||
|
||||
if (flags & MACH64_BACK) {
|
||||
|
||||
DMAOUTREG(MACH64_DST_OFF_PITCH,
|
||||
dev_priv->back_offset_pitch);
|
||||
DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x);
|
||||
DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w);
|
||||
|
||||
}
|
||||
|
||||
if (flags & MACH64_DEPTH) {
|
||||
/* Setup for depth buffer clear
|
||||
*/
|
||||
DMAOUTREG(MACH64_Z_CNTL, 0);
|
||||
DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
|
||||
|
||||
DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right);
|
||||
DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom);
|
||||
|
||||
DMAOUTREG(MACH64_CLR_CMP_CNTL, 0);
|
||||
DMAOUTREG(MACH64_GUI_TRAJ_CNTL,
|
||||
(MACH64_DST_X_LEFT_TO_RIGHT |
|
||||
MACH64_DST_Y_TOP_TO_BOTTOM));
|
||||
|
||||
DMAOUTREG(MACH64_DP_PIX_WIDTH, ((depth_bpp << 0) |
|
||||
(depth_bpp << 4) |
|
||||
(depth_bpp << 8) |
|
||||
(depth_bpp << 16) |
|
||||
(depth_bpp << 28)));
|
||||
|
||||
DMAOUTREG(MACH64_DP_FRGD_CLR, clear_depth);
|
||||
DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff);
|
||||
DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D |
|
||||
MACH64_FRGD_MIX_S));
|
||||
DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR |
|
||||
MACH64_FRGD_SRC_FRGD_CLR |
|
||||
MACH64_MONO_SRC_ONE));
|
||||
|
||||
DMAOUTREG(MACH64_DST_OFF_PITCH,
|
||||
dev_priv->depth_offset_pitch);
|
||||
DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x);
|
||||
DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w);
|
||||
}
|
||||
}
|
||||
|
||||
DMAADVANCE(dev_priv, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mach64_dma_dispatch_swap(DRMFILE filp, drm_device_t * dev)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
int nbox = sarea_priv->nbox;
|
||||
drm_clip_rect_t *pbox = sarea_priv->boxes;
|
||||
u32 fb_bpp;
|
||||
int i;
|
||||
DMALOCALS;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
switch (dev_priv->fb_bpp) {
|
||||
case 16:
|
||||
fb_bpp = MACH64_DATATYPE_RGB565;
|
||||
break;
|
||||
case 32:
|
||||
default:
|
||||
fb_bpp = MACH64_DATATYPE_ARGB8888;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!nbox)
|
||||
return 0;
|
||||
|
||||
DMAGETPTR(filp, dev_priv, 13 + nbox * 4); /* returns on failure to get buffer */
|
||||
|
||||
DMAOUTREG(MACH64_Z_CNTL, 0);
|
||||
DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
|
||||
|
||||
DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */
|
||||
DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16));
|
||||
|
||||
DMAOUTREG(MACH64_CLR_CMP_CNTL, 0);
|
||||
DMAOUTREG(MACH64_GUI_TRAJ_CNTL, (MACH64_DST_X_LEFT_TO_RIGHT |
|
||||
MACH64_DST_Y_TOP_TO_BOTTOM));
|
||||
|
||||
DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) |
|
||||
(fb_bpp << 4) |
|
||||
(fb_bpp << 8) |
|
||||
(fb_bpp << 16) | (fb_bpp << 28)));
|
||||
|
||||
DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff);
|
||||
DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S));
|
||||
DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_BKGD_CLR |
|
||||
MACH64_FRGD_SRC_BLIT | MACH64_MONO_SRC_ONE));
|
||||
|
||||
DMAOUTREG(MACH64_SRC_OFF_PITCH, dev_priv->back_offset_pitch);
|
||||
DMAOUTREG(MACH64_DST_OFF_PITCH, dev_priv->front_offset_pitch);
|
||||
|
||||
for (i = 0; i < nbox; i++) {
|
||||
int x = pbox[i].x1;
|
||||
int y = pbox[i].y1;
|
||||
int w = pbox[i].x2 - x;
|
||||
int h = pbox[i].y2 - y;
|
||||
|
||||
DRM_DEBUG("dispatch swap %d,%d-%d,%d\n",
|
||||
pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2);
|
||||
|
||||
DMAOUTREG(MACH64_SRC_WIDTH1, w);
|
||||
DMAOUTREG(MACH64_SRC_Y_X, (x << 16) | y);
|
||||
DMAOUTREG(MACH64_DST_Y_X, (x << 16) | y);
|
||||
DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w);
|
||||
|
||||
}
|
||||
|
||||
DMAADVANCE(dev_priv, 1);
|
||||
|
||||
if (dev_priv->driver_mode == MACH64_MODE_DMA_ASYNC) {
|
||||
for (i = 0; i < MACH64_MAX_QUEUED_FRAMES - 1; i++) {
|
||||
dev_priv->frame_ofs[i] = dev_priv->frame_ofs[i + 1];
|
||||
}
|
||||
dev_priv->frame_ofs[i] = GETRINGOFFSET();
|
||||
|
||||
dev_priv->sarea_priv->frames_queued++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv)
|
||||
{
|
||||
drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
int i, start;
|
||||
u32 head, tail, ofs;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
if (sarea_priv->frames_queued == 0)
|
||||
return 0;
|
||||
|
||||
tail = ring->tail;
|
||||
mach64_ring_tick(dev_priv, ring);
|
||||
head = ring->head;
|
||||
|
||||
start = (MACH64_MAX_QUEUED_FRAMES -
|
||||
DRM_MIN(MACH64_MAX_QUEUED_FRAMES, sarea_priv->frames_queued));
|
||||
|
||||
if (head == tail) {
|
||||
sarea_priv->frames_queued = 0;
|
||||
for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) {
|
||||
dev_priv->frame_ofs[i] = ~0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) {
|
||||
ofs = dev_priv->frame_ofs[i];
|
||||
DRM_DEBUG("frame_ofs[%d] ofs: %d\n", i, ofs);
|
||||
if (ofs == ~0 ||
|
||||
(head < tail && (ofs < head || ofs >= tail)) ||
|
||||
(head > tail && (ofs < head && ofs >= tail))) {
|
||||
sarea_priv->frames_queued =
|
||||
(MACH64_MAX_QUEUED_FRAMES - 1) - i;
|
||||
dev_priv->frame_ofs[i] = ~0;
|
||||
}
|
||||
}
|
||||
|
||||
return sarea_priv->frames_queued;
|
||||
}
|
||||
|
||||
/* Copy and verify a client submited buffer.
|
||||
* FIXME: Make an assembly optimized version
|
||||
*/
|
||||
static __inline__ int copy_and_verify_from_user(u32 *to,
|
||||
const u32 __user *ufrom,
|
||||
unsigned long bytes)
|
||||
{
|
||||
unsigned long n = bytes; /* dwords remaining in buffer */
|
||||
u32 *from, *orig_from;
|
||||
|
||||
from = drm_alloc(bytes, DRM_MEM_DRIVER);
|
||||
if (from == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
if (DRM_COPY_FROM_USER(from, ufrom, bytes)) {
|
||||
drm_free(from, bytes, DRM_MEM_DRIVER);
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
orig_from = from; /* we'll be modifying the "from" ptr, so save it */
|
||||
|
||||
n >>= 2;
|
||||
|
||||
while (n > 1) {
|
||||
u32 data, reg, count;
|
||||
|
||||
data = *from++;
|
||||
|
||||
n--;
|
||||
|
||||
reg = le32_to_cpu(data);
|
||||
count = (reg >> 16) + 1;
|
||||
if (count <= n) {
|
||||
n -= count;
|
||||
reg &= 0xffff;
|
||||
|
||||
/* This is an exact match of Mach64's Setup Engine registers,
|
||||
* excluding SETUP_CNTL (1_C1).
|
||||
*/
|
||||
if ((reg >= 0x0190 && reg < 0x01c1) ||
|
||||
(reg >= 0x01ca && reg <= 0x01cf)) {
|
||||
*to++ = data;
|
||||
memcpy(to, from, count << 2);
|
||||
from += count;
|
||||
to += count;
|
||||
} else {
|
||||
DRM_ERROR("%s: Got bad command: 0x%04x\n",
|
||||
__FUNCTION__, reg);
|
||||
drm_free(orig_from, bytes, DRM_MEM_DRIVER);
|
||||
return DRM_ERR(EACCES);
|
||||
}
|
||||
} else {
|
||||
DRM_ERROR
|
||||
("%s: Got bad command count(=%u) dwords remaining=%lu\n",
|
||||
__FUNCTION__, count, n);
|
||||
drm_free(orig_from, bytes, DRM_MEM_DRIVER);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
drm_free(orig_from, bytes, DRM_MEM_DRIVER);
|
||||
if (n == 0)
|
||||
return 0;
|
||||
else {
|
||||
DRM_ERROR("%s: Bad buf->used(=%lu)\n", __FUNCTION__, bytes);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev,
|
||||
int prim, void *buf, unsigned long used,
|
||||
int discard)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_buf_t *copy_buf;
|
||||
int done = 0;
|
||||
int verify_ret = 0;
|
||||
DMALOCALS;
|
||||
|
||||
DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n",
|
||||
__FUNCTION__, buf, used, sarea_priv->nbox);
|
||||
|
||||
if (used) {
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
copy_buf = mach64_freelist_get(dev_priv);
|
||||
if (copy_buf == NULL) {
|
||||
DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n",
|
||||
__FUNCTION__);
|
||||
return DRM_ERR(EAGAIN);
|
||||
}
|
||||
|
||||
if ((verify_ret =
|
||||
copy_and_verify_from_user(GETBUFPTR(copy_buf), buf,
|
||||
used)) == 0) {
|
||||
|
||||
copy_buf->used = used;
|
||||
|
||||
DMASETPTR(copy_buf);
|
||||
|
||||
if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) {
|
||||
ret = mach64_emit_state(filp, dev_priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
do {
|
||||
/* Emit the next cliprect */
|
||||
if (i < sarea_priv->nbox) {
|
||||
ret =
|
||||
mach64_emit_cliprect(filp, dev_priv,
|
||||
&sarea_priv->
|
||||
boxes[i]);
|
||||
if (ret < 0) {
|
||||
/* failed to get buffer */
|
||||
return ret;
|
||||
} else if (ret != 0) {
|
||||
/* null intersection with scissor */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((i >= sarea_priv->nbox - 1))
|
||||
done = 1;
|
||||
|
||||
/* Add the buffer to the DMA queue */
|
||||
DMAADVANCE(dev_priv, done);
|
||||
|
||||
} while (++i < sarea_priv->nbox);
|
||||
}
|
||||
|
||||
if (copy_buf->pending && !done) {
|
||||
DMADISCARDBUF();
|
||||
} else if (!done) {
|
||||
/* This buffer wasn't used (no cliprects or verify failed), so place it back
|
||||
* on the free list
|
||||
*/
|
||||
struct list_head *ptr;
|
||||
drm_mach64_freelist_t *entry;
|
||||
#if MACH64_EXTRA_CHECKING
|
||||
list_for_each(ptr, &dev_priv->pending) {
|
||||
entry =
|
||||
list_entry(ptr, drm_mach64_freelist_t,
|
||||
list);
|
||||
if (copy_buf == entry->buf) {
|
||||
DRM_ERROR
|
||||
("%s: Trying to release a pending buf\n",
|
||||
__FUNCTION__);
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ptr = dev_priv->placeholders.next;
|
||||
entry = list_entry(ptr, drm_mach64_freelist_t, list);
|
||||
copy_buf->pending = 0;
|
||||
copy_buf->used = 0;
|
||||
entry->buf = copy_buf;
|
||||
entry->discard = 1;
|
||||
list_del(ptr);
|
||||
list_add_tail(ptr, &dev_priv->free_list);
|
||||
}
|
||||
}
|
||||
|
||||
sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS;
|
||||
sarea_priv->nbox = 0;
|
||||
|
||||
return verify_ret;
|
||||
}
|
||||
|
||||
static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev,
|
||||
drm_mach64_blit_t * blit)
|
||||
{
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int dword_shift, dwords;
|
||||
drm_buf_t *buf;
|
||||
DMALOCALS;
|
||||
|
||||
/* The compiler won't optimize away a division by a variable,
|
||||
* even if the only legal values are powers of two. Thus, we'll
|
||||
* use a shift instead.
|
||||
*/
|
||||
switch (blit->format) {
|
||||
case MACH64_DATATYPE_ARGB8888:
|
||||
dword_shift = 0;
|
||||
break;
|
||||
case MACH64_DATATYPE_ARGB1555:
|
||||
case MACH64_DATATYPE_RGB565:
|
||||
case MACH64_DATATYPE_VYUY422:
|
||||
case MACH64_DATATYPE_YVYU422:
|
||||
case MACH64_DATATYPE_ARGB4444:
|
||||
dword_shift = 1;
|
||||
break;
|
||||
case MACH64_DATATYPE_CI8:
|
||||
case MACH64_DATATYPE_RGB8:
|
||||
dword_shift = 2;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("invalid blit format %d\n", blit->format);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* Dispatch the blit buffer.
|
||||
*/
|
||||
buf = dma->buflist[blit->idx];
|
||||
|
||||
if (buf->filp != filp) {
|
||||
DRM_ERROR("process %d (filp %p) using buffer with filp %p\n",
|
||||
DRM_CURRENTPID, filp, buf->filp);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (buf->pending) {
|
||||
DRM_ERROR("sending pending buffer %d\n", blit->idx);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* Set buf->used to the bytes of blit data based on the blit dimensions
|
||||
* and verify the size. When the setup is emitted to the buffer with
|
||||
* the DMA* macros below, buf->used is incremented to include the bytes
|
||||
* used for setup as well as the blit data.
|
||||
*/
|
||||
dwords = (blit->width * blit->height) >> dword_shift;
|
||||
buf->used = dwords << 2;
|
||||
if (buf->used <= 0 ||
|
||||
buf->used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) {
|
||||
DRM_ERROR("Invalid blit size: %d bytes\n", buf->used);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* FIXME: Use a last buffer flag and reduce the state emitted for subsequent,
|
||||
* continuation buffers?
|
||||
*/
|
||||
|
||||
/* Blit via BM_HOSTDATA (gui-master) - like HOST_DATA[0-15], but doesn't require
|
||||
* a register command every 16 dwords. State setup is added at the start of the
|
||||
* buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET
|
||||
*/
|
||||
DMASETPTR(buf);
|
||||
|
||||
DMAOUTREG(MACH64_Z_CNTL, 0);
|
||||
DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
|
||||
|
||||
DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */
|
||||
DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16));
|
||||
|
||||
DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); /* disable */
|
||||
DMAOUTREG(MACH64_GUI_TRAJ_CNTL,
|
||||
MACH64_DST_X_LEFT_TO_RIGHT | MACH64_DST_Y_TOP_TO_BOTTOM);
|
||||
|
||||
DMAOUTREG(MACH64_DP_PIX_WIDTH, (blit->format << 0) /* dst pix width */
|
||||
|(blit->format << 4) /* composite pix width */
|
||||
|(blit->format << 8) /* src pix width */
|
||||
|(blit->format << 16) /* host data pix width */
|
||||
|(blit->format << 28) /* scaler/3D pix width */
|
||||
);
|
||||
|
||||
DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff); /* enable all planes */
|
||||
DMAOUTREG(MACH64_DP_MIX, MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S);
|
||||
DMAOUTREG(MACH64_DP_SRC,
|
||||
MACH64_BKGD_SRC_BKGD_CLR
|
||||
| MACH64_FRGD_SRC_HOST | MACH64_MONO_SRC_ONE);
|
||||
|
||||
DMAOUTREG(MACH64_DST_OFF_PITCH,
|
||||
(blit->pitch << 22) | (blit->offset >> 3));
|
||||
DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x);
|
||||
DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width);
|
||||
|
||||
DRM_DEBUG("%s: %d bytes\n", __FUNCTION__, buf->used);
|
||||
|
||||
/* Add the buffer to the queue */
|
||||
DMAADVANCEHOSTDATA(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* IOCTL functions
|
||||
*/
|
||||
|
||||
int mach64_dma_clear(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mach64_clear_t clear;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(clear, (drm_mach64_clear_t *) data,
|
||||
sizeof(clear));
|
||||
|
||||
if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
|
||||
|
||||
ret = mach64_dma_dispatch_clear(filp, dev, clear.flags,
|
||||
clear.x, clear.y, clear.w, clear.h,
|
||||
clear.clear_color, clear.clear_depth);
|
||||
|
||||
/* Make sure we restore the 3D state next time.
|
||||
*/
|
||||
sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mach64_dma_swap(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
|
||||
|
||||
ret = mach64_dma_dispatch_swap(filp, dev);
|
||||
|
||||
/* Make sure we restore the 3D state next time.
|
||||
*/
|
||||
sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mach64_dma_vertex(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mach64_vertex_t vertex;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(vertex, (drm_mach64_vertex_t *) data,
|
||||
sizeof(vertex));
|
||||
|
||||
DRM_DEBUG("%s: pid=%d buf=%p used=%lu discard=%d\n",
|
||||
__FUNCTION__, DRM_CURRENTPID,
|
||||
vertex.buf, vertex.used, vertex.discard);
|
||||
|
||||
if (vertex.prim < 0 || vertex.prim > MACH64_PRIM_POLYGON) {
|
||||
DRM_ERROR("buffer prim %d\n", vertex.prim);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (vertex.used > MACH64_BUFFER_SIZE || (vertex.used & 3) != 0) {
|
||||
DRM_ERROR("Invalid vertex buffer size: %lu bytes\n",
|
||||
vertex.used);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
|
||||
|
||||
return mach64_dma_dispatch_vertex(filp, dev, vertex.prim, vertex.buf,
|
||||
vertex.used, vertex.discard);
|
||||
}
|
||||
|
||||
int mach64_dma_blit(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mach64_blit_t blit;
|
||||
int ret;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(blit, (drm_mach64_blit_t *) data,
|
||||
sizeof(blit));
|
||||
|
||||
DRM_DEBUG("%s: pid=%d index=%d\n",
|
||||
__FUNCTION__, DRM_CURRENTPID, blit.idx);
|
||||
|
||||
if (blit.idx < 0 || blit.idx >= dma->buf_count) {
|
||||
DRM_ERROR("buffer index %d (of %d max)\n",
|
||||
blit.idx, dma->buf_count - 1);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
ret = mach64_dma_dispatch_blit(filp, dev, &blit);
|
||||
|
||||
/* Make sure we restore the 3D state next time.
|
||||
*/
|
||||
sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT |
|
||||
MACH64_UPLOAD_MISC | MACH64_UPLOAD_CLIPRECTS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mach64_get_param(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_mach64_private_t *dev_priv = dev->dev_private;
|
||||
drm_mach64_getparam_t param;
|
||||
int value;
|
||||
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(param, (drm_mach64_getparam_t *) data,
|
||||
sizeof(param));
|
||||
|
||||
switch (param.param) {
|
||||
case MACH64_PARAM_FRAMES_QUEUED:
|
||||
/* Needs lock since it calls mach64_ring_tick() */
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
value = mach64_do_get_frames_queued(dev_priv);
|
||||
break;
|
||||
case MACH64_PARAM_IRQ_NR:
|
||||
value = dev->irq;
|
||||
break;
|
||||
default:
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
|
||||
DRM_ERROR("copy_to_user\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,430 @@
|
|||
/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*-
|
||||
* Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Jeff Hartmann <jhartmann@valinux.com>
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*
|
||||
* Rewritten by:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mga_drm.h,v 1.7 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __MGA_DRM_H__
|
||||
#define __MGA_DRM_H__
|
||||
|
||||
/* WARNING: If you change any of these defines, make sure to change the
|
||||
* defines in the Xserver file (mga_sarea.h)
|
||||
*/
|
||||
|
||||
#ifndef __MGA_SAREA_DEFINES__
|
||||
#define __MGA_SAREA_DEFINES__
|
||||
|
||||
/* WARP pipe flags
|
||||
*/
|
||||
#define MGA_F 0x1 /* fog */
|
||||
#define MGA_A 0x2 /* alpha */
|
||||
#define MGA_S 0x4 /* specular */
|
||||
#define MGA_T2 0x8 /* multitexture */
|
||||
|
||||
#define MGA_WARP_TGZ 0
|
||||
#define MGA_WARP_TGZF (MGA_F)
|
||||
#define MGA_WARP_TGZA (MGA_A)
|
||||
#define MGA_WARP_TGZAF (MGA_F|MGA_A)
|
||||
#define MGA_WARP_TGZS (MGA_S)
|
||||
#define MGA_WARP_TGZSF (MGA_S|MGA_F)
|
||||
#define MGA_WARP_TGZSA (MGA_S|MGA_A)
|
||||
#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A)
|
||||
#define MGA_WARP_T2GZ (MGA_T2)
|
||||
#define MGA_WARP_T2GZF (MGA_T2|MGA_F)
|
||||
#define MGA_WARP_T2GZA (MGA_T2|MGA_A)
|
||||
#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F)
|
||||
#define MGA_WARP_T2GZS (MGA_T2|MGA_S)
|
||||
#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F)
|
||||
#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A)
|
||||
#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A)
|
||||
|
||||
#define MGA_MAX_G200_PIPES 8 /* no multitex */
|
||||
#define MGA_MAX_G400_PIPES 16
|
||||
#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
|
||||
#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */
|
||||
|
||||
#define MGA_CARD_TYPE_G200 1
|
||||
#define MGA_CARD_TYPE_G400 2
|
||||
#define MGA_CARD_TYPE_G450 3 /* not currently used */
|
||||
#define MGA_CARD_TYPE_G550 4
|
||||
|
||||
#define MGA_FRONT 0x1
|
||||
#define MGA_BACK 0x2
|
||||
#define MGA_DEPTH 0x4
|
||||
|
||||
/* What needs to be changed for the current vertex dma buffer?
|
||||
*/
|
||||
#define MGA_UPLOAD_CONTEXT 0x1
|
||||
#define MGA_UPLOAD_TEX0 0x2
|
||||
#define MGA_UPLOAD_TEX1 0x4
|
||||
#define MGA_UPLOAD_PIPE 0x8
|
||||
#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */
|
||||
#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */
|
||||
#define MGA_UPLOAD_2D 0x40
|
||||
#define MGA_WAIT_AGE 0x80 /* handled client-side */
|
||||
#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */
|
||||
#if 0
|
||||
#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock
|
||||
quiescent */
|
||||
#endif
|
||||
|
||||
/* 32 buffers of 64k each, total 2 meg.
|
||||
*/
|
||||
#define MGA_BUFFER_SIZE (1 << 16)
|
||||
#define MGA_NUM_BUFFERS 128
|
||||
|
||||
/* Keep these small for testing.
|
||||
*/
|
||||
#define MGA_NR_SAREA_CLIPRECTS 8
|
||||
|
||||
/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
|
||||
* regions, subject to a minimum region size of (1<<16) == 64k.
|
||||
*
|
||||
* Clients may subdivide regions internally, but when sharing between
|
||||
* clients, the region size is the minimum granularity.
|
||||
*/
|
||||
|
||||
#define MGA_CARD_HEAP 0
|
||||
#define MGA_AGP_HEAP 1
|
||||
#define MGA_NR_TEX_HEAPS 2
|
||||
#define MGA_NR_TEX_REGIONS 16
|
||||
#define MGA_LOG_MIN_TEX_REGION_SIZE 16
|
||||
|
||||
#define DRM_MGA_IDLE_RETRY 2048
|
||||
|
||||
#endif /* __MGA_SAREA_DEFINES__ */
|
||||
|
||||
/* Setup registers for 3D context
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int dstorg;
|
||||
unsigned int maccess;
|
||||
unsigned int plnwt;
|
||||
unsigned int dwgctl;
|
||||
unsigned int alphactrl;
|
||||
unsigned int fogcolor;
|
||||
unsigned int wflag;
|
||||
unsigned int tdualstage0;
|
||||
unsigned int tdualstage1;
|
||||
unsigned int fcol;
|
||||
unsigned int stencil;
|
||||
unsigned int stencilctl;
|
||||
} drm_mga_context_regs_t;
|
||||
|
||||
/* Setup registers for 2D, X server
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int pitch;
|
||||
} drm_mga_server_regs_t;
|
||||
|
||||
/* Setup registers for each texture unit
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int texctl;
|
||||
unsigned int texctl2;
|
||||
unsigned int texfilter;
|
||||
unsigned int texbordercol;
|
||||
unsigned int texorg;
|
||||
unsigned int texwidth;
|
||||
unsigned int texheight;
|
||||
unsigned int texorg1;
|
||||
unsigned int texorg2;
|
||||
unsigned int texorg3;
|
||||
unsigned int texorg4;
|
||||
} drm_mga_texture_regs_t;
|
||||
|
||||
/* General aging mechanism
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int head; /* Position of head pointer */
|
||||
unsigned int wrap; /* Primary DMA wrap count */
|
||||
} drm_mga_age_t;
|
||||
|
||||
typedef struct _drm_mga_sarea {
|
||||
/* The channel for communication of state information to the kernel
|
||||
* on firing a vertex dma buffer.
|
||||
*/
|
||||
drm_mga_context_regs_t context_state;
|
||||
drm_mga_server_regs_t server_state;
|
||||
drm_mga_texture_regs_t tex_state[2];
|
||||
unsigned int warp_pipe;
|
||||
unsigned int dirty;
|
||||
unsigned int vertsize;
|
||||
|
||||
/* The current cliprects, or a subset thereof.
|
||||
*/
|
||||
drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
|
||||
unsigned int nbox;
|
||||
|
||||
/* Information about the most recently used 3d drawable. The
|
||||
* client fills in the req_* fields, the server fills in the
|
||||
* exported_ fields and puts the cliprects into boxes, above.
|
||||
*
|
||||
* The client clears the exported_drawable field before
|
||||
* clobbering the boxes data.
|
||||
*/
|
||||
unsigned int req_drawable; /* the X drawable id */
|
||||
unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */
|
||||
|
||||
unsigned int exported_drawable;
|
||||
unsigned int exported_index;
|
||||
unsigned int exported_stamp;
|
||||
unsigned int exported_buffers;
|
||||
unsigned int exported_nfront;
|
||||
unsigned int exported_nback;
|
||||
int exported_back_x, exported_front_x, exported_w;
|
||||
int exported_back_y, exported_front_y, exported_h;
|
||||
drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
|
||||
|
||||
/* Counters for aging textures and for client-side throttling.
|
||||
*/
|
||||
unsigned int status[4];
|
||||
unsigned int last_wrap;
|
||||
|
||||
drm_mga_age_t last_frame;
|
||||
unsigned int last_enqueue; /* last time a buffer was enqueued */
|
||||
unsigned int last_dispatch; /* age of the most recently dispatched buffer */
|
||||
unsigned int last_quiescent; /* */
|
||||
|
||||
/* LRU lists for texture memory in agp space and on the card.
|
||||
*/
|
||||
drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
|
||||
unsigned int texAge[MGA_NR_TEX_HEAPS];
|
||||
|
||||
/* Mechanism to validate card state.
|
||||
*/
|
||||
int ctxOwner;
|
||||
} drm_mga_sarea_t;
|
||||
|
||||
|
||||
/* MGA specific ioctls
|
||||
* The device specific ioctl range is 0x40 to 0x79.
|
||||
*/
|
||||
#define DRM_MGA_INIT 0x00
|
||||
#define DRM_MGA_FLUSH 0x01
|
||||
#define DRM_MGA_RESET 0x02
|
||||
#define DRM_MGA_SWAP 0x03
|
||||
#define DRM_MGA_CLEAR 0x04
|
||||
#define DRM_MGA_VERTEX 0x05
|
||||
#define DRM_MGA_INDICES 0x06
|
||||
#define DRM_MGA_ILOAD 0x07
|
||||
#define DRM_MGA_BLIT 0x08
|
||||
#define DRM_MGA_GETPARAM 0x09
|
||||
|
||||
/* 3.2:
|
||||
* ioctls for operating on fences.
|
||||
*/
|
||||
#define DRM_MGA_SET_FENCE 0x0a
|
||||
#define DRM_MGA_WAIT_FENCE 0x0b
|
||||
#define DRM_MGA_DMA_BOOTSTRAP 0x0c
|
||||
|
||||
|
||||
#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
|
||||
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
|
||||
#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET)
|
||||
#define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP)
|
||||
#define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t)
|
||||
#define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t)
|
||||
#define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t)
|
||||
#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t)
|
||||
#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t)
|
||||
#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t)
|
||||
#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t)
|
||||
#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t)
|
||||
#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t)
|
||||
|
||||
typedef struct _drm_mga_warp_index {
|
||||
int installed;
|
||||
unsigned long phys_addr;
|
||||
int size;
|
||||
} drm_mga_warp_index_t;
|
||||
|
||||
typedef struct drm_mga_init {
|
||||
enum {
|
||||
MGA_INIT_DMA = 0x01,
|
||||
MGA_CLEANUP_DMA = 0x02
|
||||
} func;
|
||||
|
||||
unsigned long sarea_priv_offset;
|
||||
|
||||
int chipset;
|
||||
int sgram;
|
||||
|
||||
unsigned int maccess;
|
||||
|
||||
unsigned int fb_cpp;
|
||||
unsigned int front_offset, front_pitch;
|
||||
unsigned int back_offset, back_pitch;
|
||||
|
||||
unsigned int depth_cpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
|
||||
unsigned int texture_offset[MGA_NR_TEX_HEAPS];
|
||||
unsigned int texture_size[MGA_NR_TEX_HEAPS];
|
||||
|
||||
unsigned long fb_offset;
|
||||
unsigned long mmio_offset;
|
||||
unsigned long status_offset;
|
||||
unsigned long warp_offset;
|
||||
unsigned long primary_offset;
|
||||
unsigned long buffers_offset;
|
||||
} drm_mga_init_t;
|
||||
|
||||
|
||||
typedef struct drm_mga_dma_bootstrap {
|
||||
/**
|
||||
* \name AGP texture region
|
||||
*
|
||||
* On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will
|
||||
* be filled in with the actual AGP texture settings.
|
||||
*
|
||||
* \warning
|
||||
* If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode
|
||||
* is zero, it means that PCI memory (most likely through the use of
|
||||
* an IOMMU) is being used for "AGP" textures.
|
||||
*/
|
||||
/*@{*/
|
||||
unsigned long texture_handle; /**< Handle used to map AGP textures. */
|
||||
uint32_t texture_size; /**< Size of the AGP texture region. */
|
||||
/*@}*/
|
||||
|
||||
|
||||
/**
|
||||
* Requested size of the primary DMA region.
|
||||
*
|
||||
* On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
|
||||
* filled in with the actual AGP mode. If AGP was not available
|
||||
*/
|
||||
uint32_t primary_size;
|
||||
|
||||
|
||||
/**
|
||||
* Requested number of secondary DMA buffers.
|
||||
*
|
||||
* On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
|
||||
* filled in with the actual number of secondary DMA buffers
|
||||
* allocated. Particularly when PCI DMA is used, this may be
|
||||
* (subtantially) less than the number requested.
|
||||
*/
|
||||
uint32_t secondary_bin_count;
|
||||
|
||||
|
||||
/**
|
||||
* Requested size of each secondary DMA buffer.
|
||||
*
|
||||
* While the kernel \b is free to reduce
|
||||
* dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed
|
||||
* to reduce dma_mga_dma_bootstrap::secondary_bin_size.
|
||||
*/
|
||||
uint32_t secondary_bin_size;
|
||||
|
||||
|
||||
/**
|
||||
* Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X,
|
||||
* \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is
|
||||
* zero, it means that PCI DMA should be used, even if AGP is
|
||||
* possible.
|
||||
*
|
||||
* On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
|
||||
* filled in with the actual AGP mode. If AGP was not available
|
||||
* (i.e., PCI DMA was used), this value will be zero.
|
||||
*/
|
||||
uint32_t agp_mode;
|
||||
|
||||
|
||||
/**
|
||||
* Desired AGP GART size, measured in megabytes.
|
||||
*/
|
||||
uint8_t agp_size;
|
||||
} drm_mga_dma_bootstrap_t;
|
||||
|
||||
typedef struct drm_mga_clear {
|
||||
unsigned int flags;
|
||||
unsigned int clear_color;
|
||||
unsigned int clear_depth;
|
||||
unsigned int color_mask;
|
||||
unsigned int depth_mask;
|
||||
} drm_mga_clear_t;
|
||||
|
||||
typedef struct drm_mga_vertex {
|
||||
int idx; /* buffer to queue */
|
||||
int used; /* bytes in use */
|
||||
int discard; /* client finished with buffer? */
|
||||
} drm_mga_vertex_t;
|
||||
|
||||
typedef struct drm_mga_indices {
|
||||
int idx; /* buffer to queue */
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
int discard; /* client finished with buffer? */
|
||||
} drm_mga_indices_t;
|
||||
|
||||
typedef struct drm_mga_iload {
|
||||
int idx;
|
||||
unsigned int dstorg;
|
||||
unsigned int length;
|
||||
} drm_mga_iload_t;
|
||||
|
||||
typedef struct _drm_mga_blit {
|
||||
unsigned int planemask;
|
||||
unsigned int srcorg;
|
||||
unsigned int dstorg;
|
||||
int src_pitch, dst_pitch;
|
||||
int delta_sx, delta_sy;
|
||||
int delta_dx, delta_dy;
|
||||
int height, ydir; /* flip image vertically */
|
||||
int source_pitch, dest_pitch;
|
||||
} drm_mga_blit_t;
|
||||
|
||||
/* 3.1: An ioctl to get parameters that aren't available to the 3d
|
||||
* client any other way.
|
||||
*/
|
||||
#define MGA_PARAM_IRQ_NR 1
|
||||
|
||||
/* 3.2: Query the actual card type. The DDX only distinguishes between
|
||||
* G200 chips and non-G200 chips, which it calls G400. It turns out that
|
||||
* there are some very sublte differences between the G4x0 chips and the G550
|
||||
* chips. Using this parameter query, a client-side driver can detect the
|
||||
* difference between a G4x0 and a G550.
|
||||
*/
|
||||
#define MGA_PARAM_CARD_TYPE 2
|
||||
|
||||
typedef struct drm_mga_getparam {
|
||||
int param;
|
||||
void __user *value;
|
||||
} drm_mga_getparam_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,197 @@
|
|||
/* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*-
|
||||
* Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mga_drv.c,v 1.12 2006/05/17 06:36:28 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mga_drm.h"
|
||||
#include "mga_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t mga_pciidlist[] = {
|
||||
mga_PCI_IDS
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if the device really is AGP or not.
|
||||
*
|
||||
* In addition to the usual tests performed by \c drm_device_is_agp, this
|
||||
* function detects PCI G450 cards that appear to the system exactly like
|
||||
* AGP G450 cards.
|
||||
*
|
||||
* \param dev The device to be tested.
|
||||
*
|
||||
* \returns
|
||||
* If the device is a PCI G450, zero is returned. Otherwise non-zero is
|
||||
* returned.
|
||||
*
|
||||
* \bug
|
||||
* This function needs to be filled in! The implementation in
|
||||
* linux-core/mga_drv.c shows what needs to be done.
|
||||
*/
|
||||
static int mga_driver_device_is_agp(drm_device_t * dev)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
device_t bus;
|
||||
#endif
|
||||
|
||||
/* There are PCI versions of the G450. These cards have the
|
||||
* same PCI ID as the AGP G450, but have an additional PCI-to-PCI
|
||||
* bridge chip. We detect these cards, which are not currently
|
||||
* supported by this driver, by looking at the device ID of the
|
||||
* bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the
|
||||
* device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
|
||||
* device.
|
||||
*/
|
||||
#ifdef __FreeBSD__
|
||||
#if __FreeBSD_version >= 700010
|
||||
bus = device_get_parent(device_get_parent(dev->device));
|
||||
#else
|
||||
bus = device_get_parent(dev->device);
|
||||
#endif
|
||||
if (pci_get_device(dev->device) == 0x0525 &&
|
||||
pci_get_vendor(bus) == 0x3388 &&
|
||||
pci_get_device(bus) == 0x0021)
|
||||
return DRM_IS_NOT_AGP;
|
||||
else
|
||||
return DRM_MIGHT_BE_AGP;
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
/* FIX THIS */
|
||||
return DRM_MIGHT_BE_AGP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mga_configure(drm_device_t *dev)
|
||||
{
|
||||
dev->driver.buf_priv_size = sizeof(drm_mga_buf_priv_t);
|
||||
dev->driver.load = mga_driver_load;
|
||||
dev->driver.unload = mga_driver_unload;
|
||||
dev->driver.lastclose = mga_driver_lastclose;
|
||||
dev->driver.vblank_wait = mga_driver_vblank_wait;
|
||||
dev->driver.irq_preinstall = mga_driver_irq_preinstall;
|
||||
dev->driver.irq_postinstall = mga_driver_irq_postinstall;
|
||||
dev->driver.irq_uninstall = mga_driver_irq_uninstall;
|
||||
dev->driver.irq_handler = mga_driver_irq_handler;
|
||||
dev->driver.dma_ioctl = mga_dma_buffers;
|
||||
dev->driver.dma_quiescent = mga_driver_dma_quiescent;
|
||||
dev->driver.device_is_agp = mga_driver_device_is_agp;
|
||||
|
||||
dev->driver.ioctls = mga_ioctls;
|
||||
dev->driver.max_ioctl = mga_max_ioctl;
|
||||
|
||||
dev->driver.name = DRIVER_NAME;
|
||||
dev->driver.desc = DRIVER_DESC;
|
||||
dev->driver.date = DRIVER_DATE;
|
||||
dev->driver.major = DRIVER_MAJOR;
|
||||
dev->driver.minor = DRIVER_MINOR;
|
||||
dev->driver.patchlevel = DRIVER_PATCHLEVEL;
|
||||
|
||||
dev->driver.use_agp = 1;
|
||||
dev->driver.require_agp = 1;
|
||||
dev->driver.use_mtrr = 1;
|
||||
dev->driver.use_dma = 1;
|
||||
dev->driver.use_irq = 1;
|
||||
dev->driver.use_vbl_irq = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
mga_probe(device_t dev)
|
||||
{
|
||||
return drm_probe(dev, mga_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
mga_attach(device_t nbdev)
|
||||
{
|
||||
drm_device_t *dev = device_get_softc(nbdev);
|
||||
|
||||
bzero(dev, sizeof(drm_device_t));
|
||||
mga_configure(dev);
|
||||
return drm_attach(nbdev, mga_pciidlist);
|
||||
}
|
||||
|
||||
static device_method_t mga_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, mga_probe),
|
||||
DEVMETHOD(device_attach, mga_attach),
|
||||
DEVMETHOD(device_detach, drm_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t mga_driver = {
|
||||
"drm",
|
||||
mga_methods,
|
||||
sizeof(drm_device_t)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(mga, vgapci, mga_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(mga, pci, mga_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(mga, drm, 1, 1, 1);
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
static int
|
||||
mgadrm_probe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
return drm_probe(pa, mga_pciidlist);
|
||||
}
|
||||
|
||||
static void
|
||||
mgadrm_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
drm_device_t *dev = (drm_device_t *)self;
|
||||
|
||||
mga_configure(dev);
|
||||
return drm_attach(self, pa, mga_pciidlist);
|
||||
}
|
||||
|
||||
CFATTACH_DECL(mgadrm, sizeof(drm_device_t), mgadrm_probe, mgadrm_attach,
|
||||
drm_detach, drm_activate);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,688 @@
|
|||
/* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- linux-c -*-
|
||||
* Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mga_drv.h,v 1.11 2006/04/09 20:45:45 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __MGA_DRV_H__
|
||||
#define __MGA_DRV_H__
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
|
||||
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
||||
|
||||
#define DRIVER_NAME "mga"
|
||||
#define DRIVER_DESC "Matrox G200/G400"
|
||||
#define DRIVER_DATE "20060319"
|
||||
|
||||
#define DRIVER_MAJOR 3
|
||||
#define DRIVER_MINOR 2
|
||||
#define DRIVER_PATCHLEVEL 2
|
||||
|
||||
typedef struct drm_mga_primary_buffer {
|
||||
u8 *start;
|
||||
u8 *end;
|
||||
int size;
|
||||
|
||||
u32 tail;
|
||||
int space;
|
||||
volatile long wrapped;
|
||||
|
||||
volatile u32 *status;
|
||||
|
||||
u32 last_flush;
|
||||
u32 last_wrap;
|
||||
|
||||
u32 high_mark;
|
||||
} drm_mga_primary_buffer_t;
|
||||
|
||||
typedef struct drm_mga_freelist {
|
||||
struct drm_mga_freelist *next;
|
||||
struct drm_mga_freelist *prev;
|
||||
drm_mga_age_t age;
|
||||
drm_buf_t *buf;
|
||||
} drm_mga_freelist_t;
|
||||
|
||||
typedef struct {
|
||||
drm_mga_freelist_t *list_entry;
|
||||
int discard;
|
||||
int dispatched;
|
||||
} drm_mga_buf_priv_t;
|
||||
|
||||
typedef struct drm_mga_private {
|
||||
drm_mga_primary_buffer_t prim;
|
||||
drm_mga_sarea_t *sarea_priv;
|
||||
|
||||
drm_mga_freelist_t *head;
|
||||
drm_mga_freelist_t *tail;
|
||||
|
||||
unsigned int warp_pipe;
|
||||
unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES];
|
||||
|
||||
int chipset;
|
||||
int usec_timeout;
|
||||
|
||||
/**
|
||||
* If set, the new DMA initialization sequence was used. This is
|
||||
* primarilly used to select how the driver should uninitialized its
|
||||
* internal DMA structures.
|
||||
*/
|
||||
int used_new_dma_init;
|
||||
|
||||
/**
|
||||
* If AGP memory is used for DMA buffers, this will be the value
|
||||
* \c MGA_PAGPXFER. Otherwise, it will be zero (for a PCI transfer).
|
||||
*/
|
||||
u32 dma_access;
|
||||
|
||||
/**
|
||||
* If AGP memory is used for DMA buffers, this will be the value
|
||||
* \c MGA_WAGP_ENABLE. Otherwise, it will be zero (for a PCI
|
||||
* transfer).
|
||||
*/
|
||||
u32 wagp_enable;
|
||||
|
||||
/**
|
||||
* \name MMIO region parameters.
|
||||
*
|
||||
* \sa drm_mga_private_t::mmio
|
||||
*/
|
||||
/*@{*/
|
||||
u32 mmio_base; /**< Bus address of base of MMIO. */
|
||||
u32 mmio_size; /**< Size of the MMIO region. */
|
||||
/*@}*/
|
||||
|
||||
u32 clear_cmd;
|
||||
u32 maccess;
|
||||
|
||||
wait_queue_head_t fence_queue;
|
||||
atomic_t last_fence_retired;
|
||||
u32 next_fence_to_post;
|
||||
|
||||
unsigned int fb_cpp;
|
||||
unsigned int front_offset;
|
||||
unsigned int front_pitch;
|
||||
unsigned int back_offset;
|
||||
unsigned int back_pitch;
|
||||
|
||||
unsigned int depth_cpp;
|
||||
unsigned int depth_offset;
|
||||
unsigned int depth_pitch;
|
||||
|
||||
unsigned int texture_offset;
|
||||
unsigned int texture_size;
|
||||
|
||||
drm_local_map_t *sarea;
|
||||
drm_local_map_t *mmio;
|
||||
drm_local_map_t *status;
|
||||
drm_local_map_t *warp;
|
||||
drm_local_map_t *primary;
|
||||
drm_local_map_t *agp_textures;
|
||||
|
||||
unsigned long agp_handle;
|
||||
unsigned int agp_size;
|
||||
} drm_mga_private_t;
|
||||
|
||||
extern drm_ioctl_desc_t mga_ioctls[];
|
||||
extern int mga_max_ioctl;
|
||||
|
||||
/* mga_dma.c */
|
||||
extern int mga_dma_bootstrap(DRM_IOCTL_ARGS);
|
||||
extern int mga_dma_init(DRM_IOCTL_ARGS);
|
||||
extern int mga_dma_flush(DRM_IOCTL_ARGS);
|
||||
extern int mga_dma_reset(DRM_IOCTL_ARGS);
|
||||
extern int mga_dma_buffers(DRM_IOCTL_ARGS);
|
||||
extern int mga_driver_load(drm_device_t *dev, unsigned long flags);
|
||||
extern int mga_driver_unload(drm_device_t * dev);
|
||||
extern void mga_driver_lastclose(drm_device_t * dev);
|
||||
extern int mga_driver_dma_quiescent(drm_device_t * dev);
|
||||
|
||||
extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
|
||||
|
||||
extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
|
||||
extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
|
||||
extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
|
||||
|
||||
extern int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf);
|
||||
|
||||
/* mga_warp.c */
|
||||
extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
|
||||
extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
|
||||
extern int mga_warp_init(drm_mga_private_t * dev_priv);
|
||||
|
||||
/* mga_irq.c */
|
||||
extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence);
|
||||
extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
|
||||
extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void mga_driver_irq_preinstall(drm_device_t * dev);
|
||||
extern void mga_driver_irq_postinstall(drm_device_t * dev);
|
||||
extern void mga_driver_irq_uninstall(drm_device_t * dev);
|
||||
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER()
|
||||
|
||||
#if defined(__linux__) && defined(__alpha__)
|
||||
#define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle))
|
||||
#define MGA_ADDR( reg ) (MGA_BASE(reg) + reg)
|
||||
|
||||
#define MGA_DEREF( reg ) *(volatile u32 *)MGA_ADDR( reg )
|
||||
#define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg )
|
||||
|
||||
#define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg)))
|
||||
#define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg)))
|
||||
#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
|
||||
#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
|
||||
|
||||
static inline u32 _MGA_READ(u32 * addr)
|
||||
{
|
||||
DRM_MEMORYBARRIER();
|
||||
return *(volatile u32 *)addr;
|
||||
}
|
||||
#else
|
||||
#define MGA_READ8( reg ) DRM_READ8(dev_priv->mmio, (reg))
|
||||
#define MGA_READ( reg ) DRM_READ32(dev_priv->mmio, (reg))
|
||||
#define MGA_WRITE8( reg, val ) DRM_WRITE8(dev_priv->mmio, (reg), (val))
|
||||
#define MGA_WRITE( reg, val ) DRM_WRITE32(dev_priv->mmio, (reg), (val))
|
||||
#endif
|
||||
|
||||
#define DWGREG0 0x1c00
|
||||
#define DWGREG0_END 0x1dff
|
||||
#define DWGREG1 0x2c00
|
||||
#define DWGREG1_END 0x2dff
|
||||
|
||||
#define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END)
|
||||
#define DMAREG0(r) (u8)((r - DWGREG0) >> 2)
|
||||
#define DMAREG1(r) (u8)(((r - DWGREG1) >> 2) | 0x80)
|
||||
#define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
|
||||
|
||||
/* ================================================================
|
||||
* Helper macross...
|
||||
*/
|
||||
|
||||
#define MGA_EMIT_STATE( dev_priv, dirty ) \
|
||||
do { \
|
||||
if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) { \
|
||||
if ( dev_priv->chipset >= MGA_CARD_TYPE_G400 ) { \
|
||||
mga_g400_emit_state( dev_priv ); \
|
||||
} else { \
|
||||
mga_g200_emit_state( dev_priv ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRAP_TEST_WITH_RETURN( dev_priv ) \
|
||||
do { \
|
||||
if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \
|
||||
if ( mga_is_idle( dev_priv ) ) { \
|
||||
mga_do_dma_wrap_end( dev_priv ); \
|
||||
} else if ( dev_priv->prim.space < \
|
||||
dev_priv->prim.high_mark ) { \
|
||||
if ( MGA_DMA_DEBUG ) \
|
||||
DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \
|
||||
return DRM_ERR(EBUSY); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRAP_WAIT_WITH_RETURN( dev_priv ) \
|
||||
do { \
|
||||
if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \
|
||||
if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \
|
||||
if ( MGA_DMA_DEBUG ) \
|
||||
DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \
|
||||
return DRM_ERR(EBUSY); \
|
||||
} \
|
||||
mga_do_dma_wrap_end( dev_priv ); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* ================================================================
|
||||
* Primary DMA command stream
|
||||
*/
|
||||
|
||||
#define MGA_VERBOSE 0
|
||||
|
||||
#define DMA_LOCALS unsigned int write; volatile u8 *prim;
|
||||
|
||||
#define DMA_BLOCK_SIZE (5 * sizeof(u32))
|
||||
|
||||
#define BEGIN_DMA( n ) \
|
||||
do { \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \
|
||||
(n), __FUNCTION__ ); \
|
||||
DRM_INFO( " space=0x%x req=0x%Zx\n", \
|
||||
dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \
|
||||
} \
|
||||
prim = dev_priv->prim.start; \
|
||||
write = dev_priv->prim.tail; \
|
||||
} while (0)
|
||||
|
||||
#define BEGIN_DMA_WRAP() \
|
||||
do { \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \
|
||||
DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \
|
||||
} \
|
||||
prim = dev_priv->prim.start; \
|
||||
write = dev_priv->prim.tail; \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_DMA() \
|
||||
do { \
|
||||
dev_priv->prim.tail = write; \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n", \
|
||||
write, dev_priv->prim.space ); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FLUSH_DMA() \
|
||||
do { \
|
||||
if ( 0 ) { \
|
||||
DRM_INFO( "%s:\n", __FUNCTION__ ); \
|
||||
DRM_INFO( " tail=0x%06x head=0x%06lx\n", \
|
||||
dev_priv->prim.tail, \
|
||||
MGA_READ( MGA_PRIMADDRESS ) - \
|
||||
dev_priv->primary->offset ); \
|
||||
} \
|
||||
if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) { \
|
||||
if ( dev_priv->prim.space < \
|
||||
dev_priv->prim.high_mark ) { \
|
||||
mga_do_dma_wrap_start( dev_priv ); \
|
||||
} else { \
|
||||
mga_do_dma_flush( dev_priv ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Never use this, always use DMA_BLOCK(...) for primary DMA output.
|
||||
*/
|
||||
#define DMA_WRITE( offset, val ) \
|
||||
do { \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \
|
||||
(u32)(val), write + (offset) * sizeof(u32) ); \
|
||||
} \
|
||||
*(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \
|
||||
} while (0)
|
||||
|
||||
#define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 ) \
|
||||
do { \
|
||||
DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) | \
|
||||
(DMAREG( reg1 ) << 8) | \
|
||||
(DMAREG( reg2 ) << 16) | \
|
||||
(DMAREG( reg3 ) << 24)) ); \
|
||||
DMA_WRITE( 1, val0 ); \
|
||||
DMA_WRITE( 2, val1 ); \
|
||||
DMA_WRITE( 3, val2 ); \
|
||||
DMA_WRITE( 4, val3 ); \
|
||||
write += DMA_BLOCK_SIZE; \
|
||||
} while (0)
|
||||
|
||||
/* Buffer aging via primary DMA stream head pointer.
|
||||
*/
|
||||
|
||||
#define SET_AGE( age, h, w ) \
|
||||
do { \
|
||||
(age)->head = h; \
|
||||
(age)->wrap = w; \
|
||||
} while (0)
|
||||
|
||||
#define TEST_AGE( age, h, w ) ( (age)->wrap < w || \
|
||||
( (age)->wrap == w && \
|
||||
(age)->head < h ) )
|
||||
|
||||
#define AGE_BUFFER( buf_priv ) \
|
||||
do { \
|
||||
drm_mga_freelist_t *entry = (buf_priv)->list_entry; \
|
||||
if ( (buf_priv)->dispatched ) { \
|
||||
entry->age.head = (dev_priv->prim.tail + \
|
||||
dev_priv->primary->offset); \
|
||||
entry->age.wrap = dev_priv->sarea_priv->last_wrap; \
|
||||
} else { \
|
||||
entry->age.head = 0; \
|
||||
entry->age.wrap = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MGA_ENGINE_IDLE_MASK (MGA_SOFTRAPEN | \
|
||||
MGA_DWGENGSTS | \
|
||||
MGA_ENDPRDMASTS)
|
||||
#define MGA_DMA_IDLE_MASK (MGA_SOFTRAPEN | \
|
||||
MGA_ENDPRDMASTS)
|
||||
|
||||
#define MGA_DMA_DEBUG 0
|
||||
|
||||
/* A reduced set of the mga registers.
|
||||
*/
|
||||
#define MGA_CRTC_INDEX 0x1fd4
|
||||
#define MGA_CRTC_DATA 0x1fd5
|
||||
|
||||
/* CRTC11 */
|
||||
#define MGA_VINTCLR (1 << 4)
|
||||
#define MGA_VINTEN (1 << 5)
|
||||
|
||||
#define MGA_ALPHACTRL 0x2c7c
|
||||
#define MGA_AR0 0x1c60
|
||||
#define MGA_AR1 0x1c64
|
||||
#define MGA_AR2 0x1c68
|
||||
#define MGA_AR3 0x1c6c
|
||||
#define MGA_AR4 0x1c70
|
||||
#define MGA_AR5 0x1c74
|
||||
#define MGA_AR6 0x1c78
|
||||
|
||||
#define MGA_CXBNDRY 0x1c80
|
||||
#define MGA_CXLEFT 0x1ca0
|
||||
#define MGA_CXRIGHT 0x1ca4
|
||||
|
||||
#define MGA_DMAPAD 0x1c54
|
||||
#define MGA_DSTORG 0x2cb8
|
||||
#define MGA_DWGCTL 0x1c00
|
||||
# define MGA_OPCOD_MASK (15 << 0)
|
||||
# define MGA_OPCOD_TRAP (4 << 0)
|
||||
# define MGA_OPCOD_TEXTURE_TRAP (6 << 0)
|
||||
# define MGA_OPCOD_BITBLT (8 << 0)
|
||||
# define MGA_OPCOD_ILOAD (9 << 0)
|
||||
# define MGA_ATYPE_MASK (7 << 4)
|
||||
# define MGA_ATYPE_RPL (0 << 4)
|
||||
# define MGA_ATYPE_RSTR (1 << 4)
|
||||
# define MGA_ATYPE_ZI (3 << 4)
|
||||
# define MGA_ATYPE_BLK (4 << 4)
|
||||
# define MGA_ATYPE_I (7 << 4)
|
||||
# define MGA_LINEAR (1 << 7)
|
||||
# define MGA_ZMODE_MASK (7 << 8)
|
||||
# define MGA_ZMODE_NOZCMP (0 << 8)
|
||||
# define MGA_ZMODE_ZE (2 << 8)
|
||||
# define MGA_ZMODE_ZNE (3 << 8)
|
||||
# define MGA_ZMODE_ZLT (4 << 8)
|
||||
# define MGA_ZMODE_ZLTE (5 << 8)
|
||||
# define MGA_ZMODE_ZGT (6 << 8)
|
||||
# define MGA_ZMODE_ZGTE (7 << 8)
|
||||
# define MGA_SOLID (1 << 11)
|
||||
# define MGA_ARZERO (1 << 12)
|
||||
# define MGA_SGNZERO (1 << 13)
|
||||
# define MGA_SHIFTZERO (1 << 14)
|
||||
# define MGA_BOP_MASK (15 << 16)
|
||||
# define MGA_BOP_ZERO (0 << 16)
|
||||
# define MGA_BOP_DST (10 << 16)
|
||||
# define MGA_BOP_SRC (12 << 16)
|
||||
# define MGA_BOP_ONE (15 << 16)
|
||||
# define MGA_TRANS_SHIFT 20
|
||||
# define MGA_TRANS_MASK (15 << 20)
|
||||
# define MGA_BLTMOD_MASK (15 << 25)
|
||||
# define MGA_BLTMOD_BMONOLEF (0 << 25)
|
||||
# define MGA_BLTMOD_BMONOWF (4 << 25)
|
||||
# define MGA_BLTMOD_PLAN (1 << 25)
|
||||
# define MGA_BLTMOD_BFCOL (2 << 25)
|
||||
# define MGA_BLTMOD_BU32BGR (3 << 25)
|
||||
# define MGA_BLTMOD_BU32RGB (7 << 25)
|
||||
# define MGA_BLTMOD_BU24BGR (11 << 25)
|
||||
# define MGA_BLTMOD_BU24RGB (15 << 25)
|
||||
# define MGA_PATTERN (1 << 29)
|
||||
# define MGA_TRANSC (1 << 30)
|
||||
# define MGA_CLIPDIS (1 << 31)
|
||||
#define MGA_DWGSYNC 0x2c4c
|
||||
|
||||
#define MGA_FCOL 0x1c24
|
||||
#define MGA_FIFOSTATUS 0x1e10
|
||||
#define MGA_FOGCOL 0x1cf4
|
||||
#define MGA_FXBNDRY 0x1c84
|
||||
#define MGA_FXLEFT 0x1ca8
|
||||
#define MGA_FXRIGHT 0x1cac
|
||||
|
||||
#define MGA_ICLEAR 0x1e18
|
||||
# define MGA_SOFTRAPICLR (1 << 0)
|
||||
# define MGA_VLINEICLR (1 << 5)
|
||||
#define MGA_IEN 0x1e1c
|
||||
# define MGA_SOFTRAPIEN (1 << 0)
|
||||
# define MGA_VLINEIEN (1 << 5)
|
||||
|
||||
#define MGA_LEN 0x1c5c
|
||||
|
||||
#define MGA_MACCESS 0x1c04
|
||||
|
||||
#define MGA_PITCH 0x1c8c
|
||||
#define MGA_PLNWT 0x1c1c
|
||||
#define MGA_PRIMADDRESS 0x1e58
|
||||
# define MGA_DMA_GENERAL (0 << 0)
|
||||
# define MGA_DMA_BLIT (1 << 0)
|
||||
# define MGA_DMA_VECTOR (2 << 0)
|
||||
# define MGA_DMA_VERTEX (3 << 0)
|
||||
#define MGA_PRIMEND 0x1e5c
|
||||
# define MGA_PRIMNOSTART (1 << 0)
|
||||
# define MGA_PAGPXFER (1 << 1)
|
||||
#define MGA_PRIMPTR 0x1e50
|
||||
# define MGA_PRIMPTREN0 (1 << 0)
|
||||
# define MGA_PRIMPTREN1 (1 << 1)
|
||||
|
||||
#define MGA_RST 0x1e40
|
||||
# define MGA_SOFTRESET (1 << 0)
|
||||
# define MGA_SOFTEXTRST (1 << 1)
|
||||
|
||||
#define MGA_SECADDRESS 0x2c40
|
||||
#define MGA_SECEND 0x2c44
|
||||
#define MGA_SETUPADDRESS 0x2cd0
|
||||
#define MGA_SETUPEND 0x2cd4
|
||||
#define MGA_SGN 0x1c58
|
||||
#define MGA_SOFTRAP 0x2c48
|
||||
#define MGA_SRCORG 0x2cb4
|
||||
# define MGA_SRMMAP_MASK (1 << 0)
|
||||
# define MGA_SRCMAP_FB (0 << 0)
|
||||
# define MGA_SRCMAP_SYSMEM (1 << 0)
|
||||
# define MGA_SRCACC_MASK (1 << 1)
|
||||
# define MGA_SRCACC_PCI (0 << 1)
|
||||
# define MGA_SRCACC_AGP (1 << 1)
|
||||
#define MGA_STATUS 0x1e14
|
||||
# define MGA_SOFTRAPEN (1 << 0)
|
||||
# define MGA_VSYNCPEN (1 << 4)
|
||||
# define MGA_VLINEPEN (1 << 5)
|
||||
# define MGA_DWGENGSTS (1 << 16)
|
||||
# define MGA_ENDPRDMASTS (1 << 17)
|
||||
#define MGA_STENCIL 0x2cc8
|
||||
#define MGA_STENCILCTL 0x2ccc
|
||||
|
||||
#define MGA_TDUALSTAGE0 0x2cf8
|
||||
#define MGA_TDUALSTAGE1 0x2cfc
|
||||
#define MGA_TEXBORDERCOL 0x2c5c
|
||||
#define MGA_TEXCTL 0x2c30
|
||||
#define MGA_TEXCTL2 0x2c3c
|
||||
# define MGA_DUALTEX (1 << 7)
|
||||
# define MGA_G400_TC2_MAGIC (1 << 15)
|
||||
# define MGA_MAP1_ENABLE (1 << 31)
|
||||
#define MGA_TEXFILTER 0x2c58
|
||||
#define MGA_TEXHEIGHT 0x2c2c
|
||||
#define MGA_TEXORG 0x2c24
|
||||
# define MGA_TEXORGMAP_MASK (1 << 0)
|
||||
# define MGA_TEXORGMAP_FB (0 << 0)
|
||||
# define MGA_TEXORGMAP_SYSMEM (1 << 0)
|
||||
# define MGA_TEXORGACC_MASK (1 << 1)
|
||||
# define MGA_TEXORGACC_PCI (0 << 1)
|
||||
# define MGA_TEXORGACC_AGP (1 << 1)
|
||||
#define MGA_TEXORG1 0x2ca4
|
||||
#define MGA_TEXORG2 0x2ca8
|
||||
#define MGA_TEXORG3 0x2cac
|
||||
#define MGA_TEXORG4 0x2cb0
|
||||
#define MGA_TEXTRANS 0x2c34
|
||||
#define MGA_TEXTRANSHIGH 0x2c38
|
||||
#define MGA_TEXWIDTH 0x2c28
|
||||
|
||||
#define MGA_WACCEPTSEQ 0x1dd4
|
||||
#define MGA_WCODEADDR 0x1e6c
|
||||
#define MGA_WFLAG 0x1dc4
|
||||
#define MGA_WFLAG1 0x1de0
|
||||
#define MGA_WFLAGNB 0x1e64
|
||||
#define MGA_WFLAGNB1 0x1e08
|
||||
#define MGA_WGETMSB 0x1dc8
|
||||
#define MGA_WIADDR 0x1dc0
|
||||
#define MGA_WIADDR2 0x1dd8
|
||||
# define MGA_WMODE_SUSPEND (0 << 0)
|
||||
# define MGA_WMODE_RESUME (1 << 0)
|
||||
# define MGA_WMODE_JUMP (2 << 0)
|
||||
# define MGA_WMODE_START (3 << 0)
|
||||
# define MGA_WAGP_ENABLE (1 << 2)
|
||||
#define MGA_WMISC 0x1e70
|
||||
# define MGA_WUCODECACHE_ENABLE (1 << 0)
|
||||
# define MGA_WMASTER_ENABLE (1 << 1)
|
||||
# define MGA_WCACHEFLUSH_ENABLE (1 << 3)
|
||||
#define MGA_WVRTXSZ 0x1dcc
|
||||
|
||||
#define MGA_YBOT 0x1c9c
|
||||
#define MGA_YDST 0x1c90
|
||||
#define MGA_YDSTLEN 0x1c88
|
||||
#define MGA_YDSTORG 0x1c94
|
||||
#define MGA_YTOP 0x1c98
|
||||
|
||||
#define MGA_ZORG 0x1c0c
|
||||
|
||||
/* This finishes the current batch of commands
|
||||
*/
|
||||
#define MGA_EXEC 0x0100
|
||||
|
||||
/* AGP PLL encoding (for G200 only).
|
||||
*/
|
||||
#define MGA_AGP_PLL 0x1e4c
|
||||
# define MGA_AGP2XPLL_DISABLE (0 << 0)
|
||||
# define MGA_AGP2XPLL_ENABLE (1 << 0)
|
||||
|
||||
/* Warp registers
|
||||
*/
|
||||
#define MGA_WR0 0x2d00
|
||||
#define MGA_WR1 0x2d04
|
||||
#define MGA_WR2 0x2d08
|
||||
#define MGA_WR3 0x2d0c
|
||||
#define MGA_WR4 0x2d10
|
||||
#define MGA_WR5 0x2d14
|
||||
#define MGA_WR6 0x2d18
|
||||
#define MGA_WR7 0x2d1c
|
||||
#define MGA_WR8 0x2d20
|
||||
#define MGA_WR9 0x2d24
|
||||
#define MGA_WR10 0x2d28
|
||||
#define MGA_WR11 0x2d2c
|
||||
#define MGA_WR12 0x2d30
|
||||
#define MGA_WR13 0x2d34
|
||||
#define MGA_WR14 0x2d38
|
||||
#define MGA_WR15 0x2d3c
|
||||
#define MGA_WR16 0x2d40
|
||||
#define MGA_WR17 0x2d44
|
||||
#define MGA_WR18 0x2d48
|
||||
#define MGA_WR19 0x2d4c
|
||||
#define MGA_WR20 0x2d50
|
||||
#define MGA_WR21 0x2d54
|
||||
#define MGA_WR22 0x2d58
|
||||
#define MGA_WR23 0x2d5c
|
||||
#define MGA_WR24 0x2d60
|
||||
#define MGA_WR25 0x2d64
|
||||
#define MGA_WR26 0x2d68
|
||||
#define MGA_WR27 0x2d6c
|
||||
#define MGA_WR28 0x2d70
|
||||
#define MGA_WR29 0x2d74
|
||||
#define MGA_WR30 0x2d78
|
||||
#define MGA_WR31 0x2d7c
|
||||
#define MGA_WR32 0x2d80
|
||||
#define MGA_WR33 0x2d84
|
||||
#define MGA_WR34 0x2d88
|
||||
#define MGA_WR35 0x2d8c
|
||||
#define MGA_WR36 0x2d90
|
||||
#define MGA_WR37 0x2d94
|
||||
#define MGA_WR38 0x2d98
|
||||
#define MGA_WR39 0x2d9c
|
||||
#define MGA_WR40 0x2da0
|
||||
#define MGA_WR41 0x2da4
|
||||
#define MGA_WR42 0x2da8
|
||||
#define MGA_WR43 0x2dac
|
||||
#define MGA_WR44 0x2db0
|
||||
#define MGA_WR45 0x2db4
|
||||
#define MGA_WR46 0x2db8
|
||||
#define MGA_WR47 0x2dbc
|
||||
#define MGA_WR48 0x2dc0
|
||||
#define MGA_WR49 0x2dc4
|
||||
#define MGA_WR50 0x2dc8
|
||||
#define MGA_WR51 0x2dcc
|
||||
#define MGA_WR52 0x2dd0
|
||||
#define MGA_WR53 0x2dd4
|
||||
#define MGA_WR54 0x2dd8
|
||||
#define MGA_WR55 0x2ddc
|
||||
#define MGA_WR56 0x2de0
|
||||
#define MGA_WR57 0x2de4
|
||||
#define MGA_WR58 0x2de8
|
||||
#define MGA_WR59 0x2dec
|
||||
#define MGA_WR60 0x2df0
|
||||
#define MGA_WR61 0x2df4
|
||||
#define MGA_WR62 0x2df8
|
||||
#define MGA_WR63 0x2dfc
|
||||
# define MGA_G400_WR_MAGIC (1 << 6)
|
||||
# define MGA_G400_WR56_MAGIC 0x46480000 /* 12800.0f */
|
||||
|
||||
#define MGA_ILOAD_ALIGN 64
|
||||
#define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1)
|
||||
|
||||
#define MGA_DWGCTL_FLUSH (MGA_OPCOD_TEXTURE_TRAP | \
|
||||
MGA_ATYPE_I | \
|
||||
MGA_ZMODE_NOZCMP | \
|
||||
MGA_ARZERO | \
|
||||
MGA_SGNZERO | \
|
||||
MGA_BOP_SRC | \
|
||||
(15 << MGA_TRANS_SHIFT))
|
||||
|
||||
#define MGA_DWGCTL_CLEAR (MGA_OPCOD_TRAP | \
|
||||
MGA_ZMODE_NOZCMP | \
|
||||
MGA_SOLID | \
|
||||
MGA_ARZERO | \
|
||||
MGA_SGNZERO | \
|
||||
MGA_SHIFTZERO | \
|
||||
MGA_BOP_SRC | \
|
||||
(0 << MGA_TRANS_SHIFT) | \
|
||||
MGA_BLTMOD_BMONOLEF | \
|
||||
MGA_TRANSC | \
|
||||
MGA_CLIPDIS)
|
||||
|
||||
#define MGA_DWGCTL_COPY (MGA_OPCOD_BITBLT | \
|
||||
MGA_ATYPE_RPL | \
|
||||
MGA_SGNZERO | \
|
||||
MGA_SHIFTZERO | \
|
||||
MGA_BOP_SRC | \
|
||||
(0 << MGA_TRANS_SHIFT) | \
|
||||
MGA_BLTMOD_BFCOL | \
|
||||
MGA_CLIPDIS)
|
||||
|
||||
/* Simple idle test.
|
||||
*/
|
||||
static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv)
|
||||
{
|
||||
u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
|
||||
return (status == MGA_ENDPRDMASTS);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,155 @@
|
|||
/* mga_irq.c -- IRQ handling 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>
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mga_irq.c,v 1.6 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mga_drm.h"
|
||||
#include "mga_drv.h"
|
||||
|
||||
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *) arg;
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
int status;
|
||||
int handled = 0;
|
||||
|
||||
status = MGA_READ(MGA_STATUS);
|
||||
|
||||
/* VBLANK interrupt */
|
||||
if (status & MGA_VLINEPEN) {
|
||||
MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
/* SOFTRAP interrupt */
|
||||
if (status & MGA_SOFTRAPEN) {
|
||||
const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
|
||||
const u32 prim_end = MGA_READ(MGA_PRIMEND);
|
||||
|
||||
|
||||
MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
|
||||
|
||||
/* In addition to clearing the interrupt-pending bit, we
|
||||
* have to write to MGA_PRIMEND to re-start the DMA operation.
|
||||
*/
|
||||
if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) {
|
||||
MGA_WRITE(MGA_PRIMEND, prim_end);
|
||||
}
|
||||
|
||||
atomic_inc(&dev_priv->last_fence_retired);
|
||||
DRM_WAKEUP(&dev_priv->fence_queue);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
if ( handled ) {
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
|
||||
{
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
unsigned int cur_fence;
|
||||
int ret = 0;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using fences.
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
|
||||
(((cur_fence = atomic_read(&dev_priv->last_fence_retired))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_fence;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mga_driver_irq_preinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
|
||||
/* Disable *all* interrupts */
|
||||
MGA_WRITE(MGA_IEN, 0);
|
||||
/* Clear bits if they're already high */
|
||||
MGA_WRITE(MGA_ICLEAR, ~0);
|
||||
}
|
||||
|
||||
void mga_driver_irq_postinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
|
||||
DRM_INIT_WAITQUEUE( &dev_priv->fence_queue );
|
||||
|
||||
/* Turn on vertical blank interrupt and soft trap interrupt. */
|
||||
MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
|
||||
}
|
||||
|
||||
void mga_driver_irq_uninstall(drm_device_t * dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
/* Disable *all* interrupts */
|
||||
MGA_WRITE(MGA_IEN, 0);
|
||||
|
||||
dev->irq_enabled = 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,203 @@
|
|||
/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*-
|
||||
* Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/mga_warp.c,v 1.8 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mga_drm.h"
|
||||
#include "mga_drv.h"
|
||||
#include "mga_ucode.h"
|
||||
|
||||
#define MGA_WARP_CODE_ALIGN 256 /* in bytes */
|
||||
|
||||
#define WARP_UCODE_SIZE( which ) \
|
||||
((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
|
||||
|
||||
#define WARP_UCODE_INSTALL( which, where ) \
|
||||
do { \
|
||||
DRM_DEBUG( " pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase );\
|
||||
dev_priv->warp_pipe_phys[where] = pcbase; \
|
||||
memcpy( vcbase, which, sizeof(which) ); \
|
||||
pcbase += WARP_UCODE_SIZE( which ); \
|
||||
vcbase += WARP_UCODE_SIZE( which ); \
|
||||
} while (0)
|
||||
|
||||
static const unsigned int mga_warp_g400_microcode_size =
|
||||
(WARP_UCODE_SIZE(warp_g400_tgz) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgza) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzaf) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzf) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzs) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzsa) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzsaf) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzsf) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gz) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gza) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzaf) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzf) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzs) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzsa) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzsaf) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzsf));
|
||||
|
||||
static const unsigned int mga_warp_g200_microcode_size =
|
||||
(WARP_UCODE_SIZE(warp_g200_tgz) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgza) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzaf) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzf) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzs) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzsa) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzsaf) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzsf));
|
||||
|
||||
|
||||
unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
|
||||
{
|
||||
switch (dev_priv->chipset) {
|
||||
case MGA_CARD_TYPE_G400:
|
||||
case MGA_CARD_TYPE_G550:
|
||||
return PAGE_ALIGN(mga_warp_g400_microcode_size);
|
||||
case MGA_CARD_TYPE_G200:
|
||||
return PAGE_ALIGN(mga_warp_g200_microcode_size);
|
||||
default:
|
||||
DRM_ERROR("Unknown chipset value: 0x%x\n", dev_priv->chipset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
|
||||
{
|
||||
unsigned char *vcbase = dev_priv->warp->handle;
|
||||
unsigned long pcbase = dev_priv->warp->offset;
|
||||
|
||||
memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
|
||||
|
||||
WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
|
||||
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
|
||||
{
|
||||
unsigned char *vcbase = dev_priv->warp->handle;
|
||||
unsigned long pcbase = dev_priv->warp->offset;
|
||||
|
||||
memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
|
||||
|
||||
WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
|
||||
{
|
||||
const unsigned int size = mga_warp_microcode_size(dev_priv);
|
||||
|
||||
DRM_DEBUG("MGA ucode size = %d bytes\n", size);
|
||||
if (size > dev_priv->warp->size) {
|
||||
DRM_ERROR("microcode too large! (%u > %lu)\n",
|
||||
size, dev_priv->warp->size);
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
case MGA_CARD_TYPE_G400:
|
||||
case MGA_CARD_TYPE_G550:
|
||||
return mga_warp_install_g400_microcode(dev_priv);
|
||||
case MGA_CARD_TYPE_G200:
|
||||
return mga_warp_install_g200_microcode(dev_priv);
|
||||
default:
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
|
||||
|
||||
int mga_warp_init(drm_mga_private_t * dev_priv)
|
||||
{
|
||||
u32 wmisc;
|
||||
|
||||
/* FIXME: Get rid of these damned magic numbers...
|
||||
*/
|
||||
switch (dev_priv->chipset) {
|
||||
case MGA_CARD_TYPE_G400:
|
||||
case MGA_CARD_TYPE_G550:
|
||||
MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND);
|
||||
MGA_WRITE(MGA_WGETMSB, 0x00000E00);
|
||||
MGA_WRITE(MGA_WVRTXSZ, 0x00001807);
|
||||
MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000);
|
||||
break;
|
||||
case MGA_CARD_TYPE_G200:
|
||||
MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND);
|
||||
MGA_WRITE(MGA_WGETMSB, 0x1606);
|
||||
MGA_WRITE(MGA_WVRTXSZ, 7);
|
||||
break;
|
||||
default:
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
|
||||
MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE));
|
||||
wmisc = MGA_READ(MGA_WMISC);
|
||||
if (wmisc != WMISC_EXPECTED) {
|
||||
DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n",
|
||||
wmisc, WMISC_EXPECTED);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,953 @@
|
|||
/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
|
||||
* Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/r128_cce.c,v 1.14 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "r128_drm.h"
|
||||
#include "r128_drv.h"
|
||||
|
||||
#define R128_FIFO_DEBUG 0
|
||||
|
||||
/* CCE microcode (from ATI) */
|
||||
static u32 r128_cce_microcode[] = {
|
||||
0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
|
||||
1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
|
||||
599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
|
||||
11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
|
||||
262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
|
||||
1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
|
||||
30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
|
||||
1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
|
||||
15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
|
||||
12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
|
||||
46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
|
||||
459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
|
||||
18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
|
||||
15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
|
||||
268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
|
||||
15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
|
||||
1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
|
||||
3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
|
||||
1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
|
||||
15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
|
||||
180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
|
||||
114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
|
||||
33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
|
||||
1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
|
||||
14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
|
||||
1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
|
||||
198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
|
||||
114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
|
||||
1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
|
||||
1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
|
||||
16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
|
||||
174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
|
||||
33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
|
||||
33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
|
||||
409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static int R128_READ_PLL(drm_device_t * dev, int addr)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
|
||||
return R128_READ(R128_CLOCK_CNTL_DATA);
|
||||
}
|
||||
|
||||
#if R128_FIFO_DEBUG
|
||||
static void r128_status(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
printk("GUI_STAT = 0x%08x\n",
|
||||
(unsigned int)R128_READ(R128_GUI_STAT));
|
||||
printk("PM4_STAT = 0x%08x\n",
|
||||
(unsigned int)R128_READ(R128_PM4_STAT));
|
||||
printk("PM4_BUFFER_DL_WPTR = 0x%08x\n",
|
||||
(unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR));
|
||||
printk("PM4_BUFFER_DL_RPTR = 0x%08x\n",
|
||||
(unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR));
|
||||
printk("PM4_MICRO_CNTL = 0x%08x\n",
|
||||
(unsigned int)R128_READ(R128_PM4_MICRO_CNTL));
|
||||
printk("PM4_BUFFER_CNTL = 0x%08x\n",
|
||||
(unsigned int)R128_READ(R128_PM4_BUFFER_CNTL));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ================================================================
|
||||
* Engine, FIFO control
|
||||
*/
|
||||
|
||||
static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
u32 tmp;
|
||||
int i;
|
||||
|
||||
tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
|
||||
R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
|
||||
|
||||
for (i = 0; i < dev_priv->usec_timeout; i++) {
|
||||
if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) {
|
||||
return 0;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
#if R128_FIFO_DEBUG
|
||||
DRM_ERROR("failed!\n");
|
||||
#endif
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
|
||||
static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev_priv->usec_timeout; i++) {
|
||||
int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
|
||||
if (slots >= entries)
|
||||
return 0;
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
#if R128_FIFO_DEBUG
|
||||
DRM_ERROR("failed!\n");
|
||||
#endif
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
|
||||
static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
ret = r128_do_wait_for_fifo(dev_priv, 64);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < dev_priv->usec_timeout; i++) {
|
||||
if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
|
||||
r128_do_pixcache_flush(dev_priv);
|
||||
return 0;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
#if R128_FIFO_DEBUG
|
||||
DRM_ERROR("failed!\n");
|
||||
#endif
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* CCE control, initialization
|
||||
*/
|
||||
|
||||
/* Load the microcode for the CCE */
|
||||
static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
r128_do_wait_for_idle(dev_priv);
|
||||
|
||||
R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
|
||||
R128_WRITE(R128_PM4_MICROCODE_DATAL,
|
||||
r128_cce_microcode[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush any pending commands to the CCE. This should only be used just
|
||||
* prior to a wait for idle, as it informs the engine that the command
|
||||
* stream is ending.
|
||||
*/
|
||||
static void r128_do_cce_flush(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE;
|
||||
R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp);
|
||||
}
|
||||
|
||||
/* Wait for the CCE to go idle.
|
||||
*/
|
||||
int r128_do_cce_idle(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev_priv->usec_timeout; i++) {
|
||||
if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) {
|
||||
int pm4stat = R128_READ(R128_PM4_STAT);
|
||||
if (((pm4stat & R128_PM4_FIFOCNT_MASK) >=
|
||||
dev_priv->cce_fifo_size) &&
|
||||
!(pm4stat & (R128_PM4_BUSY |
|
||||
R128_PM4_GUI_ACTIVE))) {
|
||||
return r128_do_pixcache_flush(dev_priv);
|
||||
}
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
#if R128_FIFO_DEBUG
|
||||
DRM_ERROR("failed!\n");
|
||||
r128_status(dev_priv);
|
||||
#endif
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
|
||||
/* Start the Concurrent Command Engine.
|
||||
*/
|
||||
static void r128_do_cce_start(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
r128_do_wait_for_idle(dev_priv);
|
||||
|
||||
R128_WRITE(R128_PM4_BUFFER_CNTL,
|
||||
dev_priv->cce_mode | dev_priv->ring.size_l2qw
|
||||
| R128_PM4_BUFFER_CNTL_NOUPDATE);
|
||||
R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */
|
||||
R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
|
||||
|
||||
dev_priv->cce_running = 1;
|
||||
}
|
||||
|
||||
/* Reset the Concurrent Command Engine. This will not flush any pending
|
||||
* commands, so you must wait for the CCE command stream to complete
|
||||
* before calling this routine.
|
||||
*/
|
||||
static void r128_do_cce_reset(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
|
||||
R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
|
||||
dev_priv->ring.tail = 0;
|
||||
}
|
||||
|
||||
/* Stop the Concurrent Command Engine. This will not flush any pending
|
||||
* commands, so you must flush the command stream and wait for the CCE
|
||||
* to go idle before calling this routine.
|
||||
*/
|
||||
static void r128_do_cce_stop(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
R128_WRITE(R128_PM4_MICRO_CNTL, 0);
|
||||
R128_WRITE(R128_PM4_BUFFER_CNTL,
|
||||
R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
|
||||
|
||||
dev_priv->cce_running = 0;
|
||||
}
|
||||
|
||||
/* Reset the engine. This will stop the CCE if it is running.
|
||||
*/
|
||||
static int r128_do_engine_reset(drm_device_t * dev)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
|
||||
|
||||
r128_do_pixcache_flush(dev_priv);
|
||||
|
||||
clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
|
||||
mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
|
||||
|
||||
R128_WRITE_PLL(R128_MCLK_CNTL,
|
||||
mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
|
||||
|
||||
gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
|
||||
|
||||
/* Taken from the sample code - do not change */
|
||||
R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
|
||||
R128_READ(R128_GEN_RESET_CNTL);
|
||||
R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
|
||||
R128_READ(R128_GEN_RESET_CNTL);
|
||||
|
||||
R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
|
||||
R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
|
||||
R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
|
||||
|
||||
/* Reset the CCE ring */
|
||||
r128_do_cce_reset(dev_priv);
|
||||
|
||||
/* The CCE is no longer running after an engine reset */
|
||||
dev_priv->cce_running = 0;
|
||||
|
||||
/* Reset any pending vertex, indirect buffers */
|
||||
r128_freelist_reset(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void r128_cce_init_ring_buffer(drm_device_t * dev,
|
||||
drm_r128_private_t * dev_priv)
|
||||
{
|
||||
u32 ring_start;
|
||||
u32 tmp;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* The manual (p. 2) says this address is in "VM space". This
|
||||
* means it's an offset from the start of AGP space.
|
||||
*/
|
||||
#if __OS_HAS_AGP
|
||||
if (!dev_priv->is_pci)
|
||||
ring_start = dev_priv->cce_ring->offset - dev->agp->base;
|
||||
else
|
||||
#endif
|
||||
ring_start = dev_priv->cce_ring->offset -
|
||||
(unsigned long)dev->sg->virtual;
|
||||
|
||||
R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET);
|
||||
|
||||
R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
|
||||
R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
|
||||
|
||||
/* Set watermark control */
|
||||
R128_WRITE(R128_PM4_BUFFER_WM_CNTL,
|
||||
((R128_WATERMARK_L / 4) << R128_WMA_SHIFT)
|
||||
| ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT)
|
||||
| ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT)
|
||||
| ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT));
|
||||
|
||||
/* Force read. Why? Because it's in the examples... */
|
||||
R128_READ(R128_PM4_BUFFER_ADDR);
|
||||
|
||||
/* Turn on bus mastering */
|
||||
tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS;
|
||||
R128_WRITE(R128_BUS_CNTL, tmp);
|
||||
}
|
||||
|
||||
static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
|
||||
{
|
||||
drm_r128_private_t *dev_priv;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
|
||||
if (dev_priv == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
memset(dev_priv, 0, sizeof(drm_r128_private_t));
|
||||
|
||||
dev_priv->is_pci = init->is_pci;
|
||||
|
||||
if (dev_priv->is_pci && !dev->sg) {
|
||||
DRM_ERROR("PCI GART memory not allocated!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->usec_timeout = init->usec_timeout;
|
||||
if (dev_priv->usec_timeout < 1 ||
|
||||
dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
|
||||
DRM_DEBUG("TIMEOUT problem!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->cce_mode = init->cce_mode;
|
||||
|
||||
/* GH: Simple idle check.
|
||||
*/
|
||||
atomic_set(&dev_priv->idle_count, 0);
|
||||
|
||||
/* We don't support anything other than bus-mastering ring mode,
|
||||
* but the ring can be in either AGP or PCI space for the ring
|
||||
* read pointer.
|
||||
*/
|
||||
if ((init->cce_mode != R128_PM4_192BM) &&
|
||||
(init->cce_mode != R128_PM4_128BM_64INDBM) &&
|
||||
(init->cce_mode != R128_PM4_64BM_128INDBM) &&
|
||||
(init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) {
|
||||
DRM_DEBUG("Bad cce_mode!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
switch (init->cce_mode) {
|
||||
case R128_PM4_NONPM4:
|
||||
dev_priv->cce_fifo_size = 0;
|
||||
break;
|
||||
case R128_PM4_192PIO:
|
||||
case R128_PM4_192BM:
|
||||
dev_priv->cce_fifo_size = 192;
|
||||
break;
|
||||
case R128_PM4_128PIO_64INDBM:
|
||||
case R128_PM4_128BM_64INDBM:
|
||||
dev_priv->cce_fifo_size = 128;
|
||||
break;
|
||||
case R128_PM4_64PIO_128INDBM:
|
||||
case R128_PM4_64BM_128INDBM:
|
||||
case R128_PM4_64PIO_64VCBM_64INDBM:
|
||||
case R128_PM4_64BM_64VCBM_64INDBM:
|
||||
case R128_PM4_64PIO_64VCPIO_64INDPIO:
|
||||
dev_priv->cce_fifo_size = 64;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (init->fb_bpp) {
|
||||
case 16:
|
||||
dev_priv->color_fmt = R128_DATATYPE_RGB565;
|
||||
break;
|
||||
case 32:
|
||||
default:
|
||||
dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
|
||||
break;
|
||||
}
|
||||
dev_priv->front_offset = init->front_offset;
|
||||
dev_priv->front_pitch = init->front_pitch;
|
||||
dev_priv->back_offset = init->back_offset;
|
||||
dev_priv->back_pitch = init->back_pitch;
|
||||
|
||||
switch (init->depth_bpp) {
|
||||
case 16:
|
||||
dev_priv->depth_fmt = R128_DATATYPE_RGB565;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
default:
|
||||
dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
|
||||
break;
|
||||
}
|
||||
dev_priv->depth_offset = init->depth_offset;
|
||||
dev_priv->depth_pitch = init->depth_pitch;
|
||||
dev_priv->span_offset = init->span_offset;
|
||||
|
||||
dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) |
|
||||
(dev_priv->front_offset >> 5));
|
||||
dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) |
|
||||
(dev_priv->back_offset >> 5));
|
||||
dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
|
||||
(dev_priv->depth_offset >> 5) |
|
||||
R128_DST_TILE);
|
||||
dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
|
||||
(dev_priv->span_offset >> 5));
|
||||
|
||||
DRM_GETSAREA();
|
||||
|
||||
if (!dev_priv->sarea) {
|
||||
DRM_ERROR("could not find sarea!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
|
||||
if (!dev_priv->mmio) {
|
||||
DRM_ERROR("could not find mmio region!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
|
||||
if (!dev_priv->cce_ring) {
|
||||
DRM_ERROR("could not find cce ring region!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
|
||||
if (!dev_priv->ring_rptr) {
|
||||
DRM_ERROR("could not find ring read pointer!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
dev->agp_buffer_token = init->buffers_offset;
|
||||
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
|
||||
if (!dev->agp_buffer_map) {
|
||||
DRM_ERROR("could not find dma buffer region!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (!dev_priv->is_pci) {
|
||||
dev_priv->agp_textures =
|
||||
drm_core_findmap(dev, init->agp_textures_offset);
|
||||
if (!dev_priv->agp_textures) {
|
||||
DRM_ERROR("could not find agp texture region!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
dev_priv->sarea_priv =
|
||||
(drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle +
|
||||
init->sarea_priv_offset);
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
if (!dev_priv->is_pci) {
|
||||
drm_core_ioremap(dev_priv->cce_ring, dev);
|
||||
drm_core_ioremap(dev_priv->ring_rptr, dev);
|
||||
drm_core_ioremap(dev->agp_buffer_map, dev);
|
||||
if (!dev_priv->cce_ring->handle ||
|
||||
!dev_priv->ring_rptr->handle ||
|
||||
!dev->agp_buffer_map->handle) {
|
||||
DRM_ERROR("Could not ioremap agp regions!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset;
|
||||
dev_priv->ring_rptr->handle =
|
||||
(void *)dev_priv->ring_rptr->offset;
|
||||
dev->agp_buffer_map->handle =
|
||||
(void *)dev->agp_buffer_map->offset;
|
||||
}
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
if (!dev_priv->is_pci)
|
||||
dev_priv->cce_buffers_offset = dev->agp->base;
|
||||
else
|
||||
#endif
|
||||
dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual;
|
||||
|
||||
dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle;
|
||||
dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle
|
||||
+ init->ring_size / sizeof(u32));
|
||||
dev_priv->ring.size = init->ring_size;
|
||||
dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
|
||||
|
||||
dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
|
||||
|
||||
dev_priv->ring.high_mark = 128;
|
||||
|
||||
dev_priv->sarea_priv->last_frame = 0;
|
||||
R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
|
||||
|
||||
dev_priv->sarea_priv->last_dispatch = 0;
|
||||
R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
if (dev_priv->is_pci) {
|
||||
#endif
|
||||
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
|
||||
dev_priv->gart_info.addr = NULL;
|
||||
dev_priv->gart_info.bus_addr = 0;
|
||||
dev_priv->gart_info.is_pcie = 0;
|
||||
if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
|
||||
DRM_ERROR("failed to init PCI GART!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
|
||||
#if __OS_HAS_AGP
|
||||
}
|
||||
#endif
|
||||
|
||||
r128_cce_init_ring_buffer(dev, dev_priv);
|
||||
r128_cce_load_microcode(dev_priv);
|
||||
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
|
||||
r128_do_engine_reset(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r128_do_cleanup_cce(drm_device_t * dev)
|
||||
{
|
||||
|
||||
/* Make sure interrupts are disabled here because the uninstall ioctl
|
||||
* may not have been called from userspace and after dev_private
|
||||
* is freed, it's too late.
|
||||
*/
|
||||
if (dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
if (dev->dev_private) {
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
if (!dev_priv->is_pci) {
|
||||
if (dev_priv->cce_ring != NULL)
|
||||
drm_core_ioremapfree(dev_priv->cce_ring, dev);
|
||||
if (dev_priv->ring_rptr != NULL)
|
||||
drm_core_ioremapfree(dev_priv->ring_rptr, dev);
|
||||
if (dev->agp_buffer_map != NULL) {
|
||||
drm_core_ioremapfree(dev->agp_buffer_map, dev);
|
||||
dev->agp_buffer_map = NULL;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (dev_priv->gart_info.bus_addr)
|
||||
if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
|
||||
DRM_ERROR("failed to cleanup PCI GART!\n");
|
||||
}
|
||||
|
||||
drm_free(dev->dev_private, sizeof(drm_r128_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
dev->dev_private = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r128_cce_init(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_r128_init_t init;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(init, (drm_r128_init_t __user *) data,
|
||||
sizeof(init));
|
||||
|
||||
switch (init.func) {
|
||||
case R128_INIT_CCE:
|
||||
return r128_do_init_cce(dev, &init);
|
||||
case R128_CLEANUP_CCE:
|
||||
return r128_do_cleanup_cce(dev);
|
||||
}
|
||||
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
int r128_cce_start(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
|
||||
DRM_DEBUG("%s while CCE running\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r128_do_cce_start(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Stop the CCE. The engine must have been idled before calling this
|
||||
* routine.
|
||||
*/
|
||||
int r128_cce_stop(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
drm_r128_cce_stop_t stop;
|
||||
int ret;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *) data,
|
||||
sizeof(stop));
|
||||
|
||||
/* Flush any pending CCE commands. This ensures any outstanding
|
||||
* commands are exectuted by the engine before we turn it off.
|
||||
*/
|
||||
if (stop.flush) {
|
||||
r128_do_cce_flush(dev_priv);
|
||||
}
|
||||
|
||||
/* If we fail to make the engine go idle, we return an error
|
||||
* code so that the DRM ioctl wrapper can try again.
|
||||
*/
|
||||
if (stop.idle) {
|
||||
ret = r128_do_cce_idle(dev_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Finally, we can turn off the CCE. If the engine isn't idle,
|
||||
* we will get some dropped triangles as they won't be fully
|
||||
* rendered before the CCE is shut down.
|
||||
*/
|
||||
r128_do_cce_stop(dev_priv);
|
||||
|
||||
/* Reset the engine */
|
||||
r128_do_engine_reset(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Just reset the CCE ring. Called as part of an X Server engine reset.
|
||||
*/
|
||||
int r128_cce_reset(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_DEBUG("%s called before init done\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
r128_do_cce_reset(dev_priv);
|
||||
|
||||
/* The CCE is no longer running after an engine reset */
|
||||
dev_priv->cce_running = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r128_cce_idle(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
if (dev_priv->cce_running) {
|
||||
r128_do_cce_flush(dev_priv);
|
||||
}
|
||||
|
||||
return r128_do_cce_idle(dev_priv);
|
||||
}
|
||||
|
||||
int r128_engine_reset(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
return r128_do_engine_reset(dev);
|
||||
}
|
||||
|
||||
int r128_fullscreen(DRM_IOCTL_ARGS)
|
||||
{
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Freelist management
|
||||
*/
|
||||
#define R128_BUFFER_USED 0xffffffff
|
||||
#define R128_BUFFER_FREE 0
|
||||
|
||||
#if 0
|
||||
static int r128_freelist_init(drm_device_t * dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
drm_buf_t *buf;
|
||||
drm_r128_buf_priv_t *buf_priv;
|
||||
drm_r128_freelist_t *entry;
|
||||
int i;
|
||||
|
||||
dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
|
||||
if (dev_priv->head == NULL)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
|
||||
dev_priv->head->age = R128_BUFFER_USED;
|
||||
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
buf = dma->buflist[i];
|
||||
buf_priv = buf->dev_private;
|
||||
|
||||
entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
|
||||
if (!entry)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
entry->age = R128_BUFFER_FREE;
|
||||
entry->buf = buf;
|
||||
entry->prev = dev_priv->head;
|
||||
entry->next = dev_priv->head->next;
|
||||
if (!entry->next)
|
||||
dev_priv->tail = entry;
|
||||
|
||||
buf_priv->discard = 0;
|
||||
buf_priv->dispatched = 0;
|
||||
buf_priv->list_entry = entry;
|
||||
|
||||
dev_priv->head->next = entry;
|
||||
|
||||
if (dev_priv->head->next)
|
||||
dev_priv->head->next->prev = entry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static drm_buf_t *r128_freelist_get(drm_device_t * dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
drm_r128_buf_priv_t *buf_priv;
|
||||
drm_buf_t *buf;
|
||||
int i, t;
|
||||
|
||||
/* FIXME: Optimize -- use freelist code */
|
||||
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
buf = dma->buflist[i];
|
||||
buf_priv = buf->dev_private;
|
||||
if (buf->filp == 0)
|
||||
return buf;
|
||||
}
|
||||
|
||||
for (t = 0; t < dev_priv->usec_timeout; t++) {
|
||||
u32 done_age = R128_READ(R128_LAST_DISPATCH_REG);
|
||||
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
buf = dma->buflist[i];
|
||||
buf_priv = buf->dev_private;
|
||||
if (buf->pending && buf_priv->age <= done_age) {
|
||||
/* The buffer has been processed, so it
|
||||
* can now be used.
|
||||
*/
|
||||
buf->pending = 0;
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
DRM_DEBUG("returning NULL!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void r128_freelist_reset(drm_device_t * dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
drm_buf_t *buf = dma->buflist[i];
|
||||
drm_r128_buf_priv_t *buf_priv = buf->dev_private;
|
||||
buf_priv->age = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* CCE command submission
|
||||
*/
|
||||
|
||||
int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
|
||||
{
|
||||
drm_r128_ring_buffer_t *ring = &dev_priv->ring;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev_priv->usec_timeout; i++) {
|
||||
r128_update_ring_snapshot(dev_priv);
|
||||
if (ring->space >= n)
|
||||
return 0;
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
|
||||
/* FIXME: This is being ignored... */
|
||||
DRM_ERROR("failed!\n");
|
||||
return DRM_ERR(EBUSY);
|
||||
}
|
||||
|
||||
static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
|
||||
{
|
||||
int i;
|
||||
drm_buf_t *buf;
|
||||
|
||||
for (i = d->granted_count; i < d->request_count; i++) {
|
||||
buf = r128_freelist_get(dev);
|
||||
if (!buf)
|
||||
return DRM_ERR(EAGAIN);
|
||||
|
||||
buf->filp = filp;
|
||||
|
||||
if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
|
||||
sizeof(buf->idx)))
|
||||
return DRM_ERR(EFAULT);
|
||||
if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
|
||||
sizeof(buf->total)))
|
||||
return DRM_ERR(EFAULT);
|
||||
|
||||
d->granted_count++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r128_cce_buffers(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int ret = 0;
|
||||
drm_dma_t __user *argp = (void __user *)data;
|
||||
drm_dma_t d;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, filp);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
|
||||
|
||||
/* Please don't send us buffers.
|
||||
*/
|
||||
if (d.send_count != 0) {
|
||||
DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
|
||||
DRM_CURRENTPID, d.send_count);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* We'll send you buffers.
|
||||
*/
|
||||
if (d.request_count < 0 || d.request_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
|
||||
DRM_CURRENTPID, d.request_count, dma->buf_count);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
d.granted_count = 0;
|
||||
|
||||
if (d.request_count) {
|
||||
ret = r128_cce_get_buffers(filp, dev, &d);
|
||||
}
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,349 @@
|
|||
/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
|
||||
* Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Kevin E. Martin <martin@valinux.com>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/r128_drm.h,v 1.8 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __R128_DRM_H__
|
||||
#define __R128_DRM_H__
|
||||
|
||||
/* WARNING: If you change any of these defines, make sure to change the
|
||||
* defines in the X server file (r128_sarea.h)
|
||||
*/
|
||||
#ifndef __R128_SAREA_DEFINES__
|
||||
#define __R128_SAREA_DEFINES__
|
||||
|
||||
/* What needs to be changed for the current vertex buffer?
|
||||
*/
|
||||
#define R128_UPLOAD_CONTEXT 0x001
|
||||
#define R128_UPLOAD_SETUP 0x002
|
||||
#define R128_UPLOAD_TEX0 0x004
|
||||
#define R128_UPLOAD_TEX1 0x008
|
||||
#define R128_UPLOAD_TEX0IMAGES 0x010
|
||||
#define R128_UPLOAD_TEX1IMAGES 0x020
|
||||
#define R128_UPLOAD_CORE 0x040
|
||||
#define R128_UPLOAD_MASKS 0x080
|
||||
#define R128_UPLOAD_WINDOW 0x100
|
||||
#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */
|
||||
#define R128_REQUIRE_QUIESCENCE 0x400
|
||||
#define R128_UPLOAD_ALL 0x7ff
|
||||
|
||||
#define R128_FRONT 0x1
|
||||
#define R128_BACK 0x2
|
||||
#define R128_DEPTH 0x4
|
||||
|
||||
/* Primitive types
|
||||
*/
|
||||
#define R128_POINTS 0x1
|
||||
#define R128_LINES 0x2
|
||||
#define R128_LINE_STRIP 0x3
|
||||
#define R128_TRIANGLES 0x4
|
||||
#define R128_TRIANGLE_FAN 0x5
|
||||
#define R128_TRIANGLE_STRIP 0x6
|
||||
|
||||
/* Vertex/indirect buffer size
|
||||
*/
|
||||
#define R128_BUFFER_SIZE 16384
|
||||
|
||||
/* Byte offsets for indirect buffer data
|
||||
*/
|
||||
#define R128_INDEX_PRIM_OFFSET 20
|
||||
#define R128_HOSTDATA_BLIT_OFFSET 32
|
||||
|
||||
/* Keep these small for testing.
|
||||
*/
|
||||
#define R128_NR_SAREA_CLIPRECTS 12
|
||||
|
||||
/* There are 2 heaps (local/AGP). Each region within a heap is a
|
||||
* minimum of 64k, and there are at most 64 of them per heap.
|
||||
*/
|
||||
#define R128_LOCAL_TEX_HEAP 0
|
||||
#define R128_AGP_TEX_HEAP 1
|
||||
#define R128_NR_TEX_HEAPS 2
|
||||
#define R128_NR_TEX_REGIONS 64
|
||||
#define R128_LOG_TEX_GRANULARITY 16
|
||||
|
||||
#define R128_NR_CONTEXT_REGS 12
|
||||
|
||||
#define R128_MAX_TEXTURE_LEVELS 11
|
||||
#define R128_MAX_TEXTURE_UNITS 2
|
||||
|
||||
#endif /* __R128_SAREA_DEFINES__ */
|
||||
|
||||
typedef struct {
|
||||
/* Context state - can be written in one large chunk */
|
||||
unsigned int dst_pitch_offset_c;
|
||||
unsigned int dp_gui_master_cntl_c;
|
||||
unsigned int sc_top_left_c;
|
||||
unsigned int sc_bottom_right_c;
|
||||
unsigned int z_offset_c;
|
||||
unsigned int z_pitch_c;
|
||||
unsigned int z_sten_cntl_c;
|
||||
unsigned int tex_cntl_c;
|
||||
unsigned int misc_3d_state_cntl_reg;
|
||||
unsigned int texture_clr_cmp_clr_c;
|
||||
unsigned int texture_clr_cmp_msk_c;
|
||||
unsigned int fog_color_c;
|
||||
|
||||
/* Texture state */
|
||||
unsigned int tex_size_pitch_c;
|
||||
unsigned int constant_color_c;
|
||||
|
||||
/* Setup state */
|
||||
unsigned int pm4_vc_fpu_setup;
|
||||
unsigned int setup_cntl;
|
||||
|
||||
/* Mask state */
|
||||
unsigned int dp_write_mask;
|
||||
unsigned int sten_ref_mask_c;
|
||||
unsigned int plane_3d_mask_c;
|
||||
|
||||
/* Window state */
|
||||
unsigned int window_xy_offset;
|
||||
|
||||
/* Core state */
|
||||
unsigned int scale_3d_cntl;
|
||||
} drm_r128_context_regs_t;
|
||||
|
||||
/* Setup registers for each texture unit
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int tex_cntl;
|
||||
unsigned int tex_combine_cntl;
|
||||
unsigned int tex_size_pitch;
|
||||
unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
|
||||
unsigned int tex_border_color;
|
||||
} drm_r128_texture_regs_t;
|
||||
|
||||
typedef struct drm_r128_sarea {
|
||||
/* The channel for communication of state information to the kernel
|
||||
* on firing a vertex buffer.
|
||||
*/
|
||||
drm_r128_context_regs_t context_state;
|
||||
drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS];
|
||||
unsigned int dirty;
|
||||
unsigned int vertsize;
|
||||
unsigned int vc_format;
|
||||
|
||||
/* The current cliprects, or a subset thereof.
|
||||
*/
|
||||
drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS];
|
||||
unsigned int nbox;
|
||||
|
||||
/* Counters for client-side throttling of rendering clients.
|
||||
*/
|
||||
unsigned int last_frame;
|
||||
unsigned int last_dispatch;
|
||||
|
||||
drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
|
||||
unsigned int tex_age[R128_NR_TEX_HEAPS];
|
||||
int ctx_owner;
|
||||
int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */
|
||||
int pfCurrentPage; /* which buffer is being displayed? */
|
||||
} drm_r128_sarea_t;
|
||||
|
||||
/* WARNING: If you change any of these defines, make sure to change the
|
||||
* defines in the Xserver file (xf86drmR128.h)
|
||||
*/
|
||||
|
||||
/* Rage 128 specific ioctls
|
||||
* The device specific ioctl range is 0x40 to 0x79.
|
||||
*/
|
||||
#define DRM_R128_INIT 0x00
|
||||
#define DRM_R128_CCE_START 0x01
|
||||
#define DRM_R128_CCE_STOP 0x02
|
||||
#define DRM_R128_CCE_RESET 0x03
|
||||
#define DRM_R128_CCE_IDLE 0x04
|
||||
/* 0x05 not used */
|
||||
#define DRM_R128_RESET 0x06
|
||||
#define DRM_R128_SWAP 0x07
|
||||
#define DRM_R128_CLEAR 0x08
|
||||
#define DRM_R128_VERTEX 0x09
|
||||
#define DRM_R128_INDICES 0x0a
|
||||
#define DRM_R128_BLIT 0x0b
|
||||
#define DRM_R128_DEPTH 0x0c
|
||||
#define DRM_R128_STIPPLE 0x0d
|
||||
/* 0x0e not used */
|
||||
#define DRM_R128_INDIRECT 0x0f
|
||||
#define DRM_R128_FULLSCREEN 0x10
|
||||
#define DRM_R128_CLEAR2 0x11
|
||||
#define DRM_R128_GETPARAM 0x12
|
||||
#define DRM_R128_FLIP 0x13
|
||||
|
||||
#define DRM_IOCTL_R128_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t)
|
||||
#define DRM_IOCTL_R128_CCE_START DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_START)
|
||||
#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t)
|
||||
#define DRM_IOCTL_R128_CCE_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_RESET)
|
||||
#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_IDLE)
|
||||
/* 0x05 not used */
|
||||
#define DRM_IOCTL_R128_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_RESET)
|
||||
#define DRM_IOCTL_R128_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_R128_SWAP)
|
||||
#define DRM_IOCTL_R128_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t)
|
||||
#define DRM_IOCTL_R128_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t)
|
||||
#define DRM_IOCTL_R128_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t)
|
||||
#define DRM_IOCTL_R128_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t)
|
||||
#define DRM_IOCTL_R128_DEPTH DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t)
|
||||
#define DRM_IOCTL_R128_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t)
|
||||
/* 0x0e not used */
|
||||
#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t)
|
||||
#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t)
|
||||
#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t)
|
||||
#define DRM_IOCTL_R128_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
|
||||
#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP)
|
||||
|
||||
typedef struct drm_r128_init {
|
||||
enum {
|
||||
R128_INIT_CCE = 0x01,
|
||||
R128_CLEANUP_CCE = 0x02
|
||||
} func;
|
||||
#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
|
||||
int sarea_priv_offset;
|
||||
#else
|
||||
unsigned long sarea_priv_offset;
|
||||
#endif
|
||||
int is_pci;
|
||||
int cce_mode;
|
||||
int cce_secure;
|
||||
int ring_size;
|
||||
int usec_timeout;
|
||||
|
||||
unsigned int fb_bpp;
|
||||
unsigned int front_offset, front_pitch;
|
||||
unsigned int back_offset, back_pitch;
|
||||
unsigned int depth_bpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
unsigned int span_offset;
|
||||
|
||||
#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
|
||||
unsigned int fb_offset;
|
||||
unsigned int mmio_offset;
|
||||
unsigned int ring_offset;
|
||||
unsigned int ring_rptr_offset;
|
||||
unsigned int buffers_offset;
|
||||
unsigned int agp_textures_offset;
|
||||
#else
|
||||
unsigned long fb_offset;
|
||||
unsigned long mmio_offset;
|
||||
unsigned long ring_offset;
|
||||
unsigned long ring_rptr_offset;
|
||||
unsigned long buffers_offset;
|
||||
unsigned long agp_textures_offset;
|
||||
#endif
|
||||
} drm_r128_init_t;
|
||||
|
||||
typedef struct drm_r128_cce_stop {
|
||||
int flush;
|
||||
int idle;
|
||||
} drm_r128_cce_stop_t;
|
||||
|
||||
typedef struct drm_r128_clear {
|
||||
unsigned int flags;
|
||||
#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
|
||||
int x, y, w, h;
|
||||
#endif
|
||||
unsigned int clear_color;
|
||||
unsigned int clear_depth;
|
||||
#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
|
||||
unsigned int color_mask;
|
||||
unsigned int depth_mask;
|
||||
#endif
|
||||
} drm_r128_clear_t;
|
||||
|
||||
typedef struct drm_r128_vertex {
|
||||
int prim;
|
||||
int idx; /* Index of vertex buffer */
|
||||
int count; /* Number of vertices in buffer */
|
||||
int discard; /* Client finished with buffer? */
|
||||
} drm_r128_vertex_t;
|
||||
|
||||
typedef struct drm_r128_indices {
|
||||
int prim;
|
||||
int idx;
|
||||
int start;
|
||||
int end;
|
||||
int discard; /* Client finished with buffer? */
|
||||
} drm_r128_indices_t;
|
||||
|
||||
typedef struct drm_r128_blit {
|
||||
int idx;
|
||||
int pitch;
|
||||
int offset;
|
||||
int format;
|
||||
unsigned short x, y;
|
||||
unsigned short width, height;
|
||||
} drm_r128_blit_t;
|
||||
|
||||
typedef struct drm_r128_depth {
|
||||
enum {
|
||||
R128_WRITE_SPAN = 0x01,
|
||||
R128_WRITE_PIXELS = 0x02,
|
||||
R128_READ_SPAN = 0x03,
|
||||
R128_READ_PIXELS = 0x04
|
||||
} func;
|
||||
int n;
|
||||
int __user *x;
|
||||
int __user *y;
|
||||
unsigned int __user *buffer;
|
||||
unsigned char __user *mask;
|
||||
} drm_r128_depth_t;
|
||||
|
||||
typedef struct drm_r128_stipple {
|
||||
unsigned int __user *mask;
|
||||
} drm_r128_stipple_t;
|
||||
|
||||
typedef struct drm_r128_indirect {
|
||||
int idx;
|
||||
int start;
|
||||
int end;
|
||||
int discard;
|
||||
} drm_r128_indirect_t;
|
||||
|
||||
typedef struct drm_r128_fullscreen {
|
||||
enum {
|
||||
R128_INIT_FULLSCREEN = 0x01,
|
||||
R128_CLEANUP_FULLSCREEN = 0x02
|
||||
} func;
|
||||
} drm_r128_fullscreen_t;
|
||||
|
||||
/* 2.3: An ioctl to get parameters that aren't available to the 3d
|
||||
* client any other way.
|
||||
*/
|
||||
#define R128_PARAM_IRQ_NR 1
|
||||
|
||||
typedef struct drm_r128_getparam {
|
||||
int param;
|
||||
void __user *value;
|
||||
} drm_r128_getparam_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,143 @@
|
|||
/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
|
||||
* Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/r128_drv.c,v 1.11 2005/12/20 22:44:36 jhb Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "r128_drm.h"
|
||||
#include "r128_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t r128_pciidlist[] = {
|
||||
r128_PCI_IDS
|
||||
};
|
||||
|
||||
static void r128_configure(drm_device_t *dev)
|
||||
{
|
||||
dev->driver.buf_priv_size = sizeof(drm_r128_buf_priv_t);
|
||||
dev->driver.preclose = r128_driver_preclose;
|
||||
dev->driver.lastclose = r128_driver_lastclose;
|
||||
dev->driver.vblank_wait = r128_driver_vblank_wait;
|
||||
dev->driver.irq_preinstall = r128_driver_irq_preinstall;
|
||||
dev->driver.irq_postinstall = r128_driver_irq_postinstall;
|
||||
dev->driver.irq_uninstall = r128_driver_irq_uninstall;
|
||||
dev->driver.irq_handler = r128_driver_irq_handler;
|
||||
dev->driver.dma_ioctl = r128_cce_buffers;
|
||||
|
||||
dev->driver.ioctls = r128_ioctls;
|
||||
dev->driver.max_ioctl = r128_max_ioctl;
|
||||
|
||||
dev->driver.name = DRIVER_NAME;
|
||||
dev->driver.desc = DRIVER_DESC;
|
||||
dev->driver.date = DRIVER_DATE;
|
||||
dev->driver.major = DRIVER_MAJOR;
|
||||
dev->driver.minor = DRIVER_MINOR;
|
||||
dev->driver.patchlevel = DRIVER_PATCHLEVEL;
|
||||
|
||||
dev->driver.use_agp = 1;
|
||||
dev->driver.use_mtrr = 1;
|
||||
dev->driver.use_pci_dma = 1;
|
||||
dev->driver.use_sg = 1;
|
||||
dev->driver.use_dma = 1;
|
||||
dev->driver.use_irq = 1;
|
||||
dev->driver.use_vbl_irq = 1;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
r128_probe(device_t dev)
|
||||
{
|
||||
return drm_probe(dev, r128_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
r128_attach(device_t nbdev)
|
||||
{
|
||||
drm_device_t *dev = device_get_softc(nbdev);
|
||||
|
||||
bzero(dev, sizeof(drm_device_t));
|
||||
r128_configure(dev);
|
||||
return drm_attach(nbdev, r128_pciidlist);
|
||||
}
|
||||
|
||||
static device_method_t r128_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, r128_probe),
|
||||
DEVMETHOD(device_attach, r128_attach),
|
||||
DEVMETHOD(device_detach, drm_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t r128_driver = {
|
||||
"drm",
|
||||
r128_methods,
|
||||
sizeof(drm_device_t)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(r128, vgapci, r128_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(r128, pci, r128_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(r128, drm, 1, 1, 1);
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
static int
|
||||
r128drm_probe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
return drm_probe(pa, r128_pciidlist);
|
||||
}
|
||||
|
||||
static void
|
||||
r128drm_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
drm_device_t *dev = (drm_device_t *)self;
|
||||
|
||||
r128_configure(dev);
|
||||
return drm_attach(self, pa, r128_pciidlist);
|
||||
}
|
||||
|
||||
CFATTACH_DECL(r128drm, sizeof(drm_device_t), r128drm_probe, r128drm_attach,
|
||||
drm_detach, drm_activate);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,525 @@
|
|||
/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
|
||||
* Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Kevin E. Martin <martin@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Michel D<EFBFBD>zer <daenzerm@student.ethz.ch>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/r128_drv.h,v 1.11 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __R128_DRV_H__
|
||||
#define __R128_DRV_H__
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
|
||||
|
||||
#define DRIVER_NAME "r128"
|
||||
#define DRIVER_DESC "ATI Rage 128"
|
||||
#define DRIVER_DATE "20030725"
|
||||
|
||||
/* Interface history:
|
||||
*
|
||||
* ?? - ??
|
||||
* 2.4 - Add support for ycbcr textures (no new ioctls)
|
||||
* 2.5 - Add FLIP ioctl, disable FULLSCREEN.
|
||||
*/
|
||||
#define DRIVER_MAJOR 2
|
||||
#define DRIVER_MINOR 5
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
#define GET_RING_HEAD(dev_priv) R128_READ( R128_PM4_BUFFER_DL_RPTR )
|
||||
|
||||
typedef struct drm_r128_freelist {
|
||||
unsigned int age;
|
||||
drm_buf_t *buf;
|
||||
struct drm_r128_freelist *next;
|
||||
struct drm_r128_freelist *prev;
|
||||
} drm_r128_freelist_t;
|
||||
|
||||
typedef struct drm_r128_ring_buffer {
|
||||
u32 *start;
|
||||
u32 *end;
|
||||
int size;
|
||||
int size_l2qw;
|
||||
|
||||
u32 tail;
|
||||
u32 tail_mask;
|
||||
int space;
|
||||
|
||||
int high_mark;
|
||||
} drm_r128_ring_buffer_t;
|
||||
|
||||
typedef struct drm_r128_private {
|
||||
drm_r128_ring_buffer_t ring;
|
||||
drm_r128_sarea_t *sarea_priv;
|
||||
|
||||
int cce_mode;
|
||||
int cce_fifo_size;
|
||||
int cce_running;
|
||||
|
||||
drm_r128_freelist_t *head;
|
||||
drm_r128_freelist_t *tail;
|
||||
|
||||
int usec_timeout;
|
||||
int is_pci;
|
||||
unsigned long cce_buffers_offset;
|
||||
|
||||
atomic_t idle_count;
|
||||
|
||||
int page_flipping;
|
||||
int current_page;
|
||||
u32 crtc_offset;
|
||||
u32 crtc_offset_cntl;
|
||||
|
||||
u32 color_fmt;
|
||||
unsigned int front_offset;
|
||||
unsigned int front_pitch;
|
||||
unsigned int back_offset;
|
||||
unsigned int back_pitch;
|
||||
|
||||
u32 depth_fmt;
|
||||
unsigned int depth_offset;
|
||||
unsigned int depth_pitch;
|
||||
unsigned int span_offset;
|
||||
|
||||
u32 front_pitch_offset_c;
|
||||
u32 back_pitch_offset_c;
|
||||
u32 depth_pitch_offset_c;
|
||||
u32 span_pitch_offset_c;
|
||||
|
||||
drm_local_map_t *sarea;
|
||||
drm_local_map_t *mmio;
|
||||
drm_local_map_t *cce_ring;
|
||||
drm_local_map_t *ring_rptr;
|
||||
drm_local_map_t *agp_textures;
|
||||
drm_ati_pcigart_info gart_info;
|
||||
} drm_r128_private_t;
|
||||
|
||||
typedef struct drm_r128_buf_priv {
|
||||
u32 age;
|
||||
int prim;
|
||||
int discard;
|
||||
int dispatched;
|
||||
drm_r128_freelist_t *list_entry;
|
||||
} drm_r128_buf_priv_t;
|
||||
|
||||
extern drm_ioctl_desc_t r128_ioctls[];
|
||||
extern int r128_max_ioctl;
|
||||
|
||||
/* r128_cce.c */
|
||||
extern int r128_cce_init(DRM_IOCTL_ARGS);
|
||||
extern int r128_cce_start(DRM_IOCTL_ARGS);
|
||||
extern int r128_cce_stop(DRM_IOCTL_ARGS);
|
||||
extern int r128_cce_reset(DRM_IOCTL_ARGS);
|
||||
extern int r128_cce_idle(DRM_IOCTL_ARGS);
|
||||
extern int r128_engine_reset(DRM_IOCTL_ARGS);
|
||||
extern int r128_fullscreen(DRM_IOCTL_ARGS);
|
||||
extern int r128_cce_buffers(DRM_IOCTL_ARGS);
|
||||
|
||||
extern void r128_freelist_reset(drm_device_t * dev);
|
||||
|
||||
extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
|
||||
|
||||
extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
|
||||
extern int r128_do_cleanup_cce(drm_device_t * dev);
|
||||
|
||||
extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
|
||||
|
||||
extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void r128_driver_irq_preinstall(drm_device_t * dev);
|
||||
extern void r128_driver_irq_postinstall(drm_device_t * dev);
|
||||
extern void r128_driver_irq_uninstall(drm_device_t * dev);
|
||||
extern void r128_driver_lastclose(drm_device_t * dev);
|
||||
extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);
|
||||
|
||||
extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/* Register definitions, register access macros and drmAddMap constants
|
||||
* for Rage 128 kernel driver.
|
||||
*/
|
||||
|
||||
#define R128_AUX_SC_CNTL 0x1660
|
||||
# define R128_AUX1_SC_EN (1 << 0)
|
||||
# define R128_AUX1_SC_MODE_OR (0 << 1)
|
||||
# define R128_AUX1_SC_MODE_NAND (1 << 1)
|
||||
# define R128_AUX2_SC_EN (1 << 2)
|
||||
# define R128_AUX2_SC_MODE_OR (0 << 3)
|
||||
# define R128_AUX2_SC_MODE_NAND (1 << 3)
|
||||
# define R128_AUX3_SC_EN (1 << 4)
|
||||
# define R128_AUX3_SC_MODE_OR (0 << 5)
|
||||
# define R128_AUX3_SC_MODE_NAND (1 << 5)
|
||||
#define R128_AUX1_SC_LEFT 0x1664
|
||||
#define R128_AUX1_SC_RIGHT 0x1668
|
||||
#define R128_AUX1_SC_TOP 0x166c
|
||||
#define R128_AUX1_SC_BOTTOM 0x1670
|
||||
#define R128_AUX2_SC_LEFT 0x1674
|
||||
#define R128_AUX2_SC_RIGHT 0x1678
|
||||
#define R128_AUX2_SC_TOP 0x167c
|
||||
#define R128_AUX2_SC_BOTTOM 0x1680
|
||||
#define R128_AUX3_SC_LEFT 0x1684
|
||||
#define R128_AUX3_SC_RIGHT 0x1688
|
||||
#define R128_AUX3_SC_TOP 0x168c
|
||||
#define R128_AUX3_SC_BOTTOM 0x1690
|
||||
|
||||
#define R128_BRUSH_DATA0 0x1480
|
||||
#define R128_BUS_CNTL 0x0030
|
||||
# define R128_BUS_MASTER_DIS (1 << 6)
|
||||
|
||||
#define R128_CLOCK_CNTL_INDEX 0x0008
|
||||
#define R128_CLOCK_CNTL_DATA 0x000c
|
||||
# define R128_PLL_WR_EN (1 << 7)
|
||||
#define R128_CONSTANT_COLOR_C 0x1d34
|
||||
#define R128_CRTC_OFFSET 0x0224
|
||||
#define R128_CRTC_OFFSET_CNTL 0x0228
|
||||
# define R128_CRTC_OFFSET_FLIP_CNTL (1 << 16)
|
||||
|
||||
#define R128_DP_GUI_MASTER_CNTL 0x146c
|
||||
# define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
|
||||
# define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
|
||||
# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4)
|
||||
# define R128_GMC_BRUSH_NONE (15 << 4)
|
||||
# define R128_GMC_DST_16BPP (4 << 8)
|
||||
# define R128_GMC_DST_24BPP (5 << 8)
|
||||
# define R128_GMC_DST_32BPP (6 << 8)
|
||||
# define R128_GMC_DST_DATATYPE_SHIFT 8
|
||||
# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12)
|
||||
# define R128_DP_SRC_SOURCE_MEMORY (2 << 24)
|
||||
# define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24)
|
||||
# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28)
|
||||
# define R128_GMC_AUX_CLIP_DIS (1 << 29)
|
||||
# define R128_GMC_WR_MSK_DIS (1 << 30)
|
||||
# define R128_ROP3_S 0x00cc0000
|
||||
# define R128_ROP3_P 0x00f00000
|
||||
#define R128_DP_WRITE_MASK 0x16cc
|
||||
#define R128_DST_PITCH_OFFSET_C 0x1c80
|
||||
# define R128_DST_TILE (1 << 31)
|
||||
|
||||
#define R128_GEN_INT_CNTL 0x0040
|
||||
# define R128_CRTC_VBLANK_INT_EN (1 << 0)
|
||||
#define R128_GEN_INT_STATUS 0x0044
|
||||
# define R128_CRTC_VBLANK_INT (1 << 0)
|
||||
# define R128_CRTC_VBLANK_INT_AK (1 << 0)
|
||||
#define R128_GEN_RESET_CNTL 0x00f0
|
||||
# define R128_SOFT_RESET_GUI (1 << 0)
|
||||
|
||||
#define R128_GUI_SCRATCH_REG0 0x15e0
|
||||
#define R128_GUI_SCRATCH_REG1 0x15e4
|
||||
#define R128_GUI_SCRATCH_REG2 0x15e8
|
||||
#define R128_GUI_SCRATCH_REG3 0x15ec
|
||||
#define R128_GUI_SCRATCH_REG4 0x15f0
|
||||
#define R128_GUI_SCRATCH_REG5 0x15f4
|
||||
|
||||
#define R128_GUI_STAT 0x1740
|
||||
# define R128_GUI_FIFOCNT_MASK 0x0fff
|
||||
# define R128_GUI_ACTIVE (1 << 31)
|
||||
|
||||
#define R128_MCLK_CNTL 0x000f
|
||||
# define R128_FORCE_GCP (1 << 16)
|
||||
# define R128_FORCE_PIPE3D_CP (1 << 17)
|
||||
# define R128_FORCE_RCP (1 << 18)
|
||||
|
||||
#define R128_PC_GUI_CTLSTAT 0x1748
|
||||
#define R128_PC_NGUI_CTLSTAT 0x0184
|
||||
# define R128_PC_FLUSH_GUI (3 << 0)
|
||||
# define R128_PC_RI_GUI (1 << 2)
|
||||
# define R128_PC_FLUSH_ALL 0x00ff
|
||||
# define R128_PC_BUSY (1 << 31)
|
||||
|
||||
#define R128_PCI_GART_PAGE 0x017c
|
||||
#define R128_PRIM_TEX_CNTL_C 0x1cb0
|
||||
|
||||
#define R128_SCALE_3D_CNTL 0x1a00
|
||||
#define R128_SEC_TEX_CNTL_C 0x1d00
|
||||
#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c
|
||||
#define R128_SETUP_CNTL 0x1bc4
|
||||
#define R128_STEN_REF_MASK_C 0x1d40
|
||||
|
||||
#define R128_TEX_CNTL_C 0x1c9c
|
||||
# define R128_TEX_CACHE_FLUSH (1 << 23)
|
||||
|
||||
#define R128_WAIT_UNTIL 0x1720
|
||||
# define R128_EVENT_CRTC_OFFSET (1 << 0)
|
||||
#define R128_WINDOW_XY_OFFSET 0x1bcc
|
||||
|
||||
/* CCE registers
|
||||
*/
|
||||
#define R128_PM4_BUFFER_OFFSET 0x0700
|
||||
#define R128_PM4_BUFFER_CNTL 0x0704
|
||||
# define R128_PM4_MASK (15 << 28)
|
||||
# define R128_PM4_NONPM4 (0 << 28)
|
||||
# define R128_PM4_192PIO (1 << 28)
|
||||
# define R128_PM4_192BM (2 << 28)
|
||||
# define R128_PM4_128PIO_64INDBM (3 << 28)
|
||||
# define R128_PM4_128BM_64INDBM (4 << 28)
|
||||
# define R128_PM4_64PIO_128INDBM (5 << 28)
|
||||
# define R128_PM4_64BM_128INDBM (6 << 28)
|
||||
# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28)
|
||||
# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28)
|
||||
# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
|
||||
# define R128_PM4_BUFFER_CNTL_NOUPDATE (1 << 27)
|
||||
|
||||
#define R128_PM4_BUFFER_WM_CNTL 0x0708
|
||||
# define R128_WMA_SHIFT 0
|
||||
# define R128_WMB_SHIFT 8
|
||||
# define R128_WMC_SHIFT 16
|
||||
# define R128_WB_WM_SHIFT 24
|
||||
|
||||
#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c
|
||||
#define R128_PM4_BUFFER_DL_RPTR 0x0710
|
||||
#define R128_PM4_BUFFER_DL_WPTR 0x0714
|
||||
# define R128_PM4_BUFFER_DL_DONE (1 << 31)
|
||||
|
||||
#define R128_PM4_VC_FPU_SETUP 0x071c
|
||||
|
||||
#define R128_PM4_IW_INDOFF 0x0738
|
||||
#define R128_PM4_IW_INDSIZE 0x073c
|
||||
|
||||
#define R128_PM4_STAT 0x07b8
|
||||
# define R128_PM4_FIFOCNT_MASK 0x0fff
|
||||
# define R128_PM4_BUSY (1 << 16)
|
||||
# define R128_PM4_GUI_ACTIVE (1 << 31)
|
||||
|
||||
#define R128_PM4_MICROCODE_ADDR 0x07d4
|
||||
#define R128_PM4_MICROCODE_RADDR 0x07d8
|
||||
#define R128_PM4_MICROCODE_DATAH 0x07dc
|
||||
#define R128_PM4_MICROCODE_DATAL 0x07e0
|
||||
|
||||
#define R128_PM4_BUFFER_ADDR 0x07f0
|
||||
#define R128_PM4_MICRO_CNTL 0x07fc
|
||||
# define R128_PM4_MICRO_FREERUN (1 << 30)
|
||||
|
||||
#define R128_PM4_FIFO_DATA_EVEN 0x1000
|
||||
#define R128_PM4_FIFO_DATA_ODD 0x1004
|
||||
|
||||
/* CCE command packets
|
||||
*/
|
||||
#define R128_CCE_PACKET0 0x00000000
|
||||
#define R128_CCE_PACKET1 0x40000000
|
||||
#define R128_CCE_PACKET2 0x80000000
|
||||
#define R128_CCE_PACKET3 0xC0000000
|
||||
# define R128_CNTL_HOSTDATA_BLT 0x00009400
|
||||
# define R128_CNTL_PAINT_MULTI 0x00009A00
|
||||
# define R128_CNTL_BITBLT_MULTI 0x00009B00
|
||||
# define R128_3D_RNDR_GEN_INDX_PRIM 0x00002300
|
||||
|
||||
#define R128_CCE_PACKET_MASK 0xC0000000
|
||||
#define R128_CCE_PACKET_COUNT_MASK 0x3fff0000
|
||||
#define R128_CCE_PACKET0_REG_MASK 0x000007ff
|
||||
#define R128_CCE_PACKET1_REG0_MASK 0x000007ff
|
||||
#define R128_CCE_PACKET1_REG1_MASK 0x003ff800
|
||||
|
||||
#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000
|
||||
#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001
|
||||
#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002
|
||||
#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003
|
||||
#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
|
||||
#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
|
||||
#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
|
||||
#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007
|
||||
#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010
|
||||
#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020
|
||||
#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030
|
||||
#define R128_CCE_VC_CNTL_NUM_SHIFT 16
|
||||
|
||||
#define R128_DATATYPE_VQ 0
|
||||
#define R128_DATATYPE_CI4 1
|
||||
#define R128_DATATYPE_CI8 2
|
||||
#define R128_DATATYPE_ARGB1555 3
|
||||
#define R128_DATATYPE_RGB565 4
|
||||
#define R128_DATATYPE_RGB888 5
|
||||
#define R128_DATATYPE_ARGB8888 6
|
||||
#define R128_DATATYPE_RGB332 7
|
||||
#define R128_DATATYPE_Y8 8
|
||||
#define R128_DATATYPE_RGB8 9
|
||||
#define R128_DATATYPE_CI16 10
|
||||
#define R128_DATATYPE_YVYU422 11
|
||||
#define R128_DATATYPE_VYUY422 12
|
||||
#define R128_DATATYPE_AYUV444 14
|
||||
#define R128_DATATYPE_ARGB4444 15
|
||||
|
||||
/* Constants */
|
||||
#define R128_AGP_OFFSET 0x02000000
|
||||
|
||||
#define R128_WATERMARK_L 16
|
||||
#define R128_WATERMARK_M 8
|
||||
#define R128_WATERMARK_N 8
|
||||
#define R128_WATERMARK_K 128
|
||||
|
||||
#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
|
||||
|
||||
#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0
|
||||
#define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1
|
||||
#define R128_MAX_VB_AGE 0x7fffffff
|
||||
#define R128_MAX_VB_VERTS (0xffff)
|
||||
|
||||
#define R128_RING_HIGH_MARK 128
|
||||
|
||||
#define R128_PERFORMANCE_BOXES 0
|
||||
|
||||
#define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
|
||||
#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
|
||||
#define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
|
||||
#define R128_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) )
|
||||
|
||||
#define R128_WRITE_PLL(addr,val) \
|
||||
do { \
|
||||
R128_WRITE8(R128_CLOCK_CNTL_INDEX, \
|
||||
((addr) & 0x1f) | R128_PLL_WR_EN); \
|
||||
R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \
|
||||
} while (0)
|
||||
|
||||
#define CCE_PACKET0( reg, n ) (R128_CCE_PACKET0 | \
|
||||
((n) << 16) | ((reg) >> 2))
|
||||
#define CCE_PACKET1( reg0, reg1 ) (R128_CCE_PACKET1 | \
|
||||
(((reg1) >> 2) << 11) | ((reg0) >> 2))
|
||||
#define CCE_PACKET2() (R128_CCE_PACKET2)
|
||||
#define CCE_PACKET3( pkt, n ) (R128_CCE_PACKET3 | \
|
||||
(pkt) | ((n) << 16))
|
||||
|
||||
static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
|
||||
{
|
||||
drm_r128_ring_buffer_t *ring = &dev_priv->ring;
|
||||
ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32);
|
||||
if (ring->space <= 0)
|
||||
ring->space += ring->size;
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Misc helper macros
|
||||
*/
|
||||
|
||||
#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
|
||||
do { \
|
||||
drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \
|
||||
if ( ring->space < ring->high_mark ) { \
|
||||
for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \
|
||||
r128_update_ring_snapshot( dev_priv ); \
|
||||
if ( ring->space >= ring->high_mark ) \
|
||||
goto __ring_space_done; \
|
||||
DRM_UDELAY(1); \
|
||||
} \
|
||||
DRM_ERROR( "ring space check failed!\n" ); \
|
||||
return DRM_ERR(EBUSY); \
|
||||
} \
|
||||
__ring_space_done: \
|
||||
; \
|
||||
} while (0)
|
||||
|
||||
#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
|
||||
do { \
|
||||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; \
|
||||
if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) { \
|
||||
int __ret = r128_do_cce_idle( dev_priv ); \
|
||||
if ( __ret ) return __ret; \
|
||||
sarea_priv->last_dispatch = 0; \
|
||||
r128_freelist_reset( dev ); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define R128_WAIT_UNTIL_PAGE_FLIPPED() do { \
|
||||
OUT_RING( CCE_PACKET0( R128_WAIT_UNTIL, 0 ) ); \
|
||||
OUT_RING( R128_EVENT_CRTC_OFFSET ); \
|
||||
} while (0)
|
||||
|
||||
/* ================================================================
|
||||
* Ring control
|
||||
*/
|
||||
|
||||
#define R128_VERBOSE 0
|
||||
|
||||
#define RING_LOCALS \
|
||||
int write, _nr; unsigned int tail_mask; volatile u32 *ring;
|
||||
|
||||
#define BEGIN_RING( n ) do { \
|
||||
if ( R128_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
|
||||
(n), __FUNCTION__ ); \
|
||||
} \
|
||||
if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
|
||||
COMMIT_RING(); \
|
||||
r128_wait_ring( dev_priv, (n) * sizeof(u32) ); \
|
||||
} \
|
||||
_nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \
|
||||
ring = dev_priv->ring.start; \
|
||||
write = dev_priv->ring.tail; \
|
||||
tail_mask = dev_priv->ring.tail_mask; \
|
||||
} while (0)
|
||||
|
||||
/* You can set this to zero if you want. If the card locks up, you'll
|
||||
* need to keep this set. It works around a bug in early revs of the
|
||||
* Rage 128 chipset, where the CCE would read 32 dwords past the end of
|
||||
* the ring buffer before wrapping around.
|
||||
*/
|
||||
#define R128_BROKEN_CCE 1
|
||||
|
||||
#define ADVANCE_RING() do { \
|
||||
if ( R128_VERBOSE ) { \
|
||||
DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
|
||||
write, dev_priv->ring.tail ); \
|
||||
} \
|
||||
if ( R128_BROKEN_CCE && write < 32 ) { \
|
||||
memcpy( dev_priv->ring.end, \
|
||||
dev_priv->ring.start, \
|
||||
write * sizeof(u32) ); \
|
||||
} \
|
||||
if (((dev_priv->ring.tail + _nr) & tail_mask) != write) { \
|
||||
DRM_ERROR( \
|
||||
"ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \
|
||||
((dev_priv->ring.tail + _nr) & tail_mask), \
|
||||
write, __LINE__); \
|
||||
} else \
|
||||
dev_priv->ring.tail = write; \
|
||||
} while (0)
|
||||
|
||||
#define COMMIT_RING() do { \
|
||||
if ( R128_VERBOSE ) { \
|
||||
DRM_INFO( "COMMIT_RING() tail=0x%06x\n", \
|
||||
dev_priv->ring.tail ); \
|
||||
} \
|
||||
DRM_MEMORYBARRIER(); \
|
||||
R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail ); \
|
||||
R128_READ( R128_PM4_BUFFER_DL_WPTR ); \
|
||||
} while (0)
|
||||
|
||||
#define OUT_RING( x ) do { \
|
||||
if ( R128_VERBOSE ) { \
|
||||
DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
|
||||
(unsigned int)(x), write ); \
|
||||
} \
|
||||
ring[write++] = cpu_to_le32( x ); \
|
||||
write &= tail_mask; \
|
||||
} while (0)
|
||||
|
||||
#endif /* __R128_DRV_H__ */
|
|
@ -0,0 +1,107 @@
|
|||
/* r128_irq.c -- IRQ handling 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>
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/r128_irq.c,v 1.6 2005/11/28 23:13:53 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "r128_drm.h"
|
||||
#include "r128_drv.h"
|
||||
|
||||
irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
drm_device_t *dev = (drm_device_t *) arg;
|
||||
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
|
||||
int status;
|
||||
|
||||
status = R128_READ(R128_GEN_INT_STATUS);
|
||||
|
||||
/* VBLANK interrupt */
|
||||
if (status & R128_CRTC_VBLANK_INT) {
|
||||
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
|
||||
{
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void r128_driver_irq_preinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
|
||||
|
||||
/* Disable *all* interrupts */
|
||||
R128_WRITE(R128_GEN_INT_CNTL, 0);
|
||||
/* Clear vblank bit if it's already high */
|
||||
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
|
||||
}
|
||||
|
||||
void r128_driver_irq_postinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
|
||||
|
||||
/* Turn on VBL interrupt */
|
||||
R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
|
||||
}
|
||||
|
||||
void r128_driver_irq_uninstall(drm_device_t * dev)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
/* Disable *all* interrupts */
|
||||
R128_WRITE(R128_GEN_INT_CNTL, 0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,947 @@
|
|||
/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
|
||||
*
|
||||
* Copyright (C) The Weather Channel, Inc. 2002.
|
||||
* Copyright (C) 2004 Nicolai Haehnle.
|
||||
* 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:
|
||||
* Nicolai Haehnle <prefect_@gmx.net>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/r300_cmdbuf.c,v 1.5 2006/05/17 06:36:28 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
#include "r300_reg.h"
|
||||
|
||||
#define R300_SIMULTANEOUS_CLIPRECTS 4
|
||||
|
||||
/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
|
||||
*/
|
||||
static const int r300_cliprect_cntl[4] = {
|
||||
0xAAAA,
|
||||
0xEEEE,
|
||||
0xFEFE,
|
||||
0xFFFE
|
||||
};
|
||||
|
||||
/**
|
||||
* Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
|
||||
* buffer, starting with index n.
|
||||
*/
|
||||
static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf, int n)
|
||||
{
|
||||
drm_clip_rect_t box;
|
||||
int nr;
|
||||
int i;
|
||||
RING_LOCALS;
|
||||
|
||||
nr = cmdbuf->nbox - n;
|
||||
if (nr > R300_SIMULTANEOUS_CLIPRECTS)
|
||||
nr = R300_SIMULTANEOUS_CLIPRECTS;
|
||||
|
||||
DRM_DEBUG("%i cliprects\n", nr);
|
||||
|
||||
if (nr) {
|
||||
BEGIN_RING(6 + nr * 2);
|
||||
OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
|
||||
|
||||
for (i = 0; i < nr; ++i) {
|
||||
if (DRM_COPY_FROM_USER_UNCHECKED
|
||||
(&box, &cmdbuf->boxes[n + i], sizeof(box))) {
|
||||
DRM_ERROR("copy cliprect faulted\n");
|
||||
return DRM_ERR(EFAULT);
|
||||
}
|
||||
|
||||
box.x1 =
|
||||
(box.x1 +
|
||||
R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
|
||||
box.y1 =
|
||||
(box.y1 +
|
||||
R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
|
||||
box.x2 =
|
||||
(box.x2 +
|
||||
R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
|
||||
box.y2 =
|
||||
(box.y2 +
|
||||
R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
|
||||
|
||||
OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
|
||||
(box.y1 << R300_CLIPRECT_Y_SHIFT));
|
||||
OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
|
||||
(box.y2 << R300_CLIPRECT_Y_SHIFT));
|
||||
}
|
||||
|
||||
OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
|
||||
|
||||
/* TODO/SECURITY: Force scissors to a safe value, otherwise the
|
||||
* client might be able to trample over memory.
|
||||
* The impact should be very limited, but I'd rather be safe than
|
||||
* sorry.
|
||||
*/
|
||||
OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
|
||||
OUT_RING(0);
|
||||
OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
|
||||
ADVANCE_RING();
|
||||
} else {
|
||||
/* Why we allow zero cliprect rendering:
|
||||
* There are some commands in a command buffer that must be submitted
|
||||
* even when there are no cliprects, e.g. DMA buffer discard
|
||||
* or state setting (though state setting could be avoided by
|
||||
* simulating a loss of context).
|
||||
*
|
||||
* Now since the cmdbuf interface is so chaotic right now (and is
|
||||
* bound to remain that way for a bit until things settle down),
|
||||
* it is basically impossible to filter out the commands that are
|
||||
* necessary and those that aren't.
|
||||
*
|
||||
* So I choose the safe way and don't do any filtering at all;
|
||||
* instead, I simply set up the engine so that all rendering
|
||||
* can't produce any fragments.
|
||||
*/
|
||||
BEGIN_RING(2);
|
||||
OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 r300_reg_flags[0x10000 >> 2];
|
||||
|
||||
void r300_init_reg_flags(void)
|
||||
{
|
||||
int i;
|
||||
memset(r300_reg_flags, 0, 0x10000 >> 2);
|
||||
#define ADD_RANGE_MARK(reg, count,mark) \
|
||||
for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
|
||||
r300_reg_flags[i]|=(mark);
|
||||
|
||||
#define MARK_SAFE 1
|
||||
#define MARK_CHECK_OFFSET 2
|
||||
|
||||
#define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE)
|
||||
|
||||
/* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
|
||||
ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
|
||||
ADD_RANGE(0x2080, 1);
|
||||
ADD_RANGE(R300_SE_VTE_CNTL, 2);
|
||||
ADD_RANGE(0x2134, 2);
|
||||
ADD_RANGE(0x2140, 1);
|
||||
ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
|
||||
ADD_RANGE(0x21DC, 1);
|
||||
ADD_RANGE(0x221C, 1);
|
||||
ADD_RANGE(0x2220, 4);
|
||||
ADD_RANGE(0x2288, 1);
|
||||
ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
|
||||
ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
|
||||
ADD_RANGE(R300_GB_ENABLE, 1);
|
||||
ADD_RANGE(R300_GB_MSPOS0, 5);
|
||||
ADD_RANGE(R300_TX_CNTL, 1);
|
||||
ADD_RANGE(R300_TX_ENABLE, 1);
|
||||
ADD_RANGE(0x4200, 4);
|
||||
ADD_RANGE(0x4214, 1);
|
||||
ADD_RANGE(R300_RE_POINTSIZE, 1);
|
||||
ADD_RANGE(0x4230, 3);
|
||||
ADD_RANGE(R300_RE_LINE_CNT, 1);
|
||||
ADD_RANGE(0x4238, 1);
|
||||
ADD_RANGE(0x4260, 3);
|
||||
ADD_RANGE(0x4274, 4);
|
||||
ADD_RANGE(0x4288, 5);
|
||||
ADD_RANGE(0x42A0, 1);
|
||||
ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
|
||||
ADD_RANGE(0x42B4, 1);
|
||||
ADD_RANGE(R300_RE_CULL_CNTL, 1);
|
||||
ADD_RANGE(0x42C0, 2);
|
||||
ADD_RANGE(R300_RS_CNTL_0, 2);
|
||||
ADD_RANGE(R300_RS_INTERP_0, 8);
|
||||
ADD_RANGE(R300_RS_ROUTE_0, 8);
|
||||
ADD_RANGE(0x43A4, 2);
|
||||
ADD_RANGE(0x43E8, 1);
|
||||
ADD_RANGE(R300_PFS_CNTL_0, 3);
|
||||
ADD_RANGE(R300_PFS_NODE_0, 4);
|
||||
ADD_RANGE(R300_PFS_TEXI_0, 64);
|
||||
ADD_RANGE(0x46A4, 5);
|
||||
ADD_RANGE(R300_PFS_INSTR0_0, 64);
|
||||
ADD_RANGE(R300_PFS_INSTR1_0, 64);
|
||||
ADD_RANGE(R300_PFS_INSTR2_0, 64);
|
||||
ADD_RANGE(R300_PFS_INSTR3_0, 64);
|
||||
ADD_RANGE(0x4BC0, 1);
|
||||
ADD_RANGE(0x4BC8, 3);
|
||||
ADD_RANGE(R300_PP_ALPHA_TEST, 2);
|
||||
ADD_RANGE(0x4BD8, 1);
|
||||
ADD_RANGE(R300_PFS_PARAM_0_X, 64);
|
||||
ADD_RANGE(0x4E00, 1);
|
||||
ADD_RANGE(R300_RB3D_CBLEND, 2);
|
||||
ADD_RANGE(R300_RB3D_COLORMASK, 1);
|
||||
ADD_RANGE(0x4E10, 3);
|
||||
ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */
|
||||
ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
|
||||
ADD_RANGE(0x4E50, 9);
|
||||
ADD_RANGE(0x4E88, 1);
|
||||
ADD_RANGE(0x4EA0, 2);
|
||||
ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
|
||||
ADD_RANGE(0x4F10, 4);
|
||||
ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
|
||||
ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
|
||||
ADD_RANGE(0x4F28, 1);
|
||||
ADD_RANGE(0x4F30, 2);
|
||||
ADD_RANGE(0x4F44, 1);
|
||||
ADD_RANGE(0x4F54, 1);
|
||||
|
||||
ADD_RANGE(R300_TX_FILTER_0, 16);
|
||||
ADD_RANGE(R300_TX_FILTER1_0, 16);
|
||||
ADD_RANGE(R300_TX_SIZE_0, 16);
|
||||
ADD_RANGE(R300_TX_FORMAT_0, 16);
|
||||
ADD_RANGE(R300_TX_PITCH_0, 16);
|
||||
/* Texture offset is dangerous and needs more checking */
|
||||
ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
|
||||
ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
|
||||
ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
|
||||
|
||||
/* Sporadic registers used as primitives are emitted */
|
||||
ADD_RANGE(0x4f18, 1);
|
||||
ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
|
||||
ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
|
||||
ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
|
||||
|
||||
}
|
||||
|
||||
static __inline__ int r300_check_range(unsigned reg, int count)
|
||||
{
|
||||
int i;
|
||||
if (reg & ~0xffff)
|
||||
return -1;
|
||||
for (i = (reg >> 2); i < (reg >> 2) + count; i++)
|
||||
if (r300_reg_flags[i] != MARK_SAFE)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* we expect offsets passed to the framebuffer to be either within video
|
||||
* memory or within AGP space
|
||||
*/
|
||||
static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
|
||||
u32 offset)
|
||||
{
|
||||
/* we realy want to check against end of video aperture
|
||||
but this value is not being kept.
|
||||
This code is correct for now (does the same thing as the
|
||||
code that sets MC_FB_LOCATION) in radeon_cp.c */
|
||||
if (offset >= dev_priv->fb_location &&
|
||||
offset < (dev_priv->fb_location + dev_priv->fb_size))
|
||||
return 0;
|
||||
if (offset >= dev_priv->gart_vm_start &&
|
||||
offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
|
||||
dev_priv,
|
||||
drm_radeon_kcmd_buffer_t
|
||||
* cmdbuf,
|
||||
drm_r300_cmd_header_t
|
||||
header)
|
||||
{
|
||||
int reg;
|
||||
int sz;
|
||||
int i;
|
||||
int values[64];
|
||||
RING_LOCALS;
|
||||
|
||||
sz = header.packet0.count;
|
||||
reg = (header.packet0.reghi << 8) | header.packet0.reglo;
|
||||
|
||||
if ((sz > 64) || (sz < 0)) {
|
||||
DRM_ERROR
|
||||
("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
|
||||
reg, sz);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
for (i = 0; i < sz; i++) {
|
||||
values[i] = ((int *)cmdbuf->buf)[i];
|
||||
switch (r300_reg_flags[(reg >> 2) + i]) {
|
||||
case MARK_SAFE:
|
||||
break;
|
||||
case MARK_CHECK_OFFSET:
|
||||
if (r300_check_offset(dev_priv, (u32) values[i])) {
|
||||
DRM_ERROR
|
||||
("Offset failed range check (reg=%04x sz=%d)\n",
|
||||
reg, sz);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Register %04x failed check as flag=%02x\n",
|
||||
reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_RING(1 + sz);
|
||||
OUT_RING(CP_PACKET0(reg, sz - 1));
|
||||
OUT_RING_TABLE(values, sz);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * 4;
|
||||
cmdbuf->bufsz -= sz * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a packet0 setting arbitrary registers.
|
||||
* Called by r300_do_cp_cmdbuf.
|
||||
*
|
||||
* Note that checks are performed on contents and addresses of the registers
|
||||
*/
|
||||
static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf,
|
||||
drm_r300_cmd_header_t header)
|
||||
{
|
||||
int reg;
|
||||
int sz;
|
||||
RING_LOCALS;
|
||||
|
||||
sz = header.packet0.count;
|
||||
reg = (header.packet0.reghi << 8) | header.packet0.reglo;
|
||||
|
||||
if (!sz)
|
||||
return 0;
|
||||
|
||||
if (sz * 4 > cmdbuf->bufsz)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
if (reg + sz * 4 >= 0x10000) {
|
||||
DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
|
||||
sz);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (r300_check_range(reg, sz)) {
|
||||
/* go and check everything */
|
||||
return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
|
||||
header);
|
||||
}
|
||||
/* the rest of the data is safe to emit, whatever the values the user passed */
|
||||
|
||||
BEGIN_RING(1 + sz);
|
||||
OUT_RING(CP_PACKET0(reg, sz - 1));
|
||||
OUT_RING_TABLE((int *)cmdbuf->buf, sz);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * 4;
|
||||
cmdbuf->bufsz -= sz * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads user-supplied vertex program instructions or parameters onto
|
||||
* the graphics card.
|
||||
* Called by r300_do_cp_cmdbuf.
|
||||
*/
|
||||
static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf,
|
||||
drm_r300_cmd_header_t header)
|
||||
{
|
||||
int sz;
|
||||
int addr;
|
||||
RING_LOCALS;
|
||||
|
||||
sz = header.vpu.count;
|
||||
addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
|
||||
|
||||
if (!sz)
|
||||
return 0;
|
||||
if (sz * 16 > cmdbuf->bufsz)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
BEGIN_RING(5 + sz * 4);
|
||||
/* Wait for VAP to come to senses.. */
|
||||
/* there is no need to emit it multiple times, (only once before VAP is programmed,
|
||||
but this optimization is for later */
|
||||
OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
|
||||
OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
|
||||
OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
|
||||
OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
|
||||
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += sz * 16;
|
||||
cmdbuf->bufsz -= sz * 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a clear packet from userspace.
|
||||
* Called by r300_emit_packet3.
|
||||
*/
|
||||
static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||
{
|
||||
RING_LOCALS;
|
||||
|
||||
if (8 * 4 > cmdbuf->bufsz)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
BEGIN_RING(10);
|
||||
OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
|
||||
OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
|
||||
(1 << R300_PRIM_NUM_VERTICES_SHIFT));
|
||||
OUT_RING_TABLE((int *)cmdbuf->buf, 8);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += 8 * 4;
|
||||
cmdbuf->bufsz -= 8 * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf,
|
||||
u32 header)
|
||||
{
|
||||
int count, i, k;
|
||||
#define MAX_ARRAY_PACKET 64
|
||||
u32 payload[MAX_ARRAY_PACKET];
|
||||
u32 narrays;
|
||||
RING_LOCALS;
|
||||
|
||||
count = (header >> 16) & 0x3fff;
|
||||
|
||||
if ((count + 1) > MAX_ARRAY_PACKET) {
|
||||
DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
|
||||
count);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
memset(payload, 0, MAX_ARRAY_PACKET * 4);
|
||||
memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
|
||||
|
||||
/* carefully check packet contents */
|
||||
|
||||
narrays = payload[0];
|
||||
k = 0;
|
||||
i = 1;
|
||||
while ((k < narrays) && (i < (count + 1))) {
|
||||
i++; /* skip attribute field */
|
||||
if (r300_check_offset(dev_priv, payload[i])) {
|
||||
DRM_ERROR
|
||||
("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
|
||||
k, i);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
k++;
|
||||
i++;
|
||||
if (k == narrays)
|
||||
break;
|
||||
/* have one more to process, they come in pairs */
|
||||
if (r300_check_offset(dev_priv, payload[i])) {
|
||||
DRM_ERROR
|
||||
("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
|
||||
k, i);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
k++;
|
||||
i++;
|
||||
}
|
||||
/* do the counts match what we expect ? */
|
||||
if ((k != narrays) || (i != (count + 1))) {
|
||||
DRM_ERROR
|
||||
("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
|
||||
k, i, narrays, count + 1);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* all clear, output packet */
|
||||
|
||||
BEGIN_RING(count + 2);
|
||||
OUT_RING(header);
|
||||
OUT_RING_TABLE(payload, count + 1);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += (count + 2) * 4;
|
||||
cmdbuf->bufsz -= (count + 2) * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||
{
|
||||
u32 *cmd = (u32 *) cmdbuf->buf;
|
||||
int count, ret;
|
||||
RING_LOCALS;
|
||||
|
||||
count=(cmd[0]>>16) & 0x3fff;
|
||||
|
||||
if (cmd[0] & 0x8000) {
|
||||
u32 offset;
|
||||
|
||||
if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
||||
| RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
|
||||
offset = cmd[2] << 10;
|
||||
ret = r300_check_offset(dev_priv, offset);
|
||||
if (ret) {
|
||||
DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
|
||||
(cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
|
||||
offset = cmd[3] << 10;
|
||||
ret = r300_check_offset(dev_priv, offset);
|
||||
if (ret) {
|
||||
DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_RING(count+2);
|
||||
OUT_RING(cmd[0]);
|
||||
OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += (count+2)*4;
|
||||
cmdbuf->bufsz -= (count+2)*4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||
{
|
||||
u32 header;
|
||||
int count;
|
||||
RING_LOCALS;
|
||||
|
||||
if (4 > cmdbuf->bufsz)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
/* Fixme !! This simply emits a packet without much checking.
|
||||
We need to be smarter. */
|
||||
|
||||
/* obtain first word - actual packet3 header */
|
||||
header = *(u32 *) cmdbuf->buf;
|
||||
|
||||
/* Is it packet 3 ? */
|
||||
if ((header >> 30) != 0x3) {
|
||||
DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
count = (header >> 16) & 0x3fff;
|
||||
|
||||
/* Check again now that we know how much data to expect */
|
||||
if ((count + 2) * 4 > cmdbuf->bufsz) {
|
||||
DRM_ERROR
|
||||
("Expected packet3 of length %d but have only %d bytes left\n",
|
||||
(count + 2) * 4, cmdbuf->bufsz);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
/* Is it a packet type we know about ? */
|
||||
switch (header & 0xff00) {
|
||||
case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */
|
||||
return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
|
||||
|
||||
case RADEON_CNTL_BITBLT_MULTI:
|
||||
return r300_emit_bitblt_multi(dev_priv, cmdbuf);
|
||||
|
||||
case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */
|
||||
case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */
|
||||
case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */
|
||||
case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
|
||||
case RADEON_WAIT_FOR_IDLE:
|
||||
case RADEON_CP_NOP:
|
||||
/* these packets are safe */
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
BEGIN_RING(count + 2);
|
||||
OUT_RING(header);
|
||||
OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
|
||||
ADVANCE_RING();
|
||||
|
||||
cmdbuf->buf += (count + 2) * 4;
|
||||
cmdbuf->bufsz -= (count + 2) * 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a rendering packet3 from userspace.
|
||||
* Called by r300_do_cp_cmdbuf.
|
||||
*/
|
||||
static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf,
|
||||
drm_r300_cmd_header_t header)
|
||||
{
|
||||
int n;
|
||||
int ret;
|
||||
char *orig_buf = cmdbuf->buf;
|
||||
int orig_bufsz = cmdbuf->bufsz;
|
||||
|
||||
/* This is a do-while-loop so that we run the interior at least once,
|
||||
* even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
|
||||
*/
|
||||
n = 0;
|
||||
do {
|
||||
if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
|
||||
ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmdbuf->buf = orig_buf;
|
||||
cmdbuf->bufsz = orig_bufsz;
|
||||
}
|
||||
|
||||
switch (header.packet3.packet) {
|
||||
case R300_CMD_PACKET3_CLEAR:
|
||||
DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
|
||||
ret = r300_emit_clear(dev_priv, cmdbuf);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_clear failed\n");
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case R300_CMD_PACKET3_RAW:
|
||||
DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
|
||||
ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_raw_packet3 failed\n");
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DRM_ERROR("bad packet3 type %i at %p\n",
|
||||
header.packet3.packet,
|
||||
cmdbuf->buf - sizeof(header));
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
n += R300_SIMULTANEOUS_CLIPRECTS;
|
||||
} while (n < cmdbuf->nbox);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Some of the R300 chips seem to be extremely touchy about the two registers
|
||||
* that are configured in r300_pacify.
|
||||
* Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
|
||||
* sends a command buffer that contains only state setting commands and a
|
||||
* vertex program/parameter upload sequence, this will eventually lead to a
|
||||
* lockup, unless the sequence is bracketed by calls to r300_pacify.
|
||||
* So we should take great care to *always* call r300_pacify before
|
||||
* *anything* 3D related, and again afterwards. This is what the
|
||||
* call bracket in r300_do_cp_cmdbuf is for.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Emit the sequence to pacify R300.
|
||||
*/
|
||||
static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
RING_LOCALS;
|
||||
|
||||
BEGIN_RING(6);
|
||||
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
|
||||
OUT_RING(0xa);
|
||||
OUT_RING(CP_PACKET0(0x4f18, 0));
|
||||
OUT_RING(0x3);
|
||||
OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
|
||||
OUT_RING(0x0);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
|
||||
* The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
|
||||
* be careful about how this function is called.
|
||||
*/
|
||||
static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
|
||||
|
||||
buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
|
||||
buf->pending = 1;
|
||||
buf->used = 0;
|
||||
}
|
||||
|
||||
static int r300_scratch(drm_radeon_private_t *dev_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf,
|
||||
drm_r300_cmd_header_t header)
|
||||
{
|
||||
u32 *ref_age_base;
|
||||
u32 i, buf_idx, h_pending;
|
||||
RING_LOCALS;
|
||||
|
||||
if (cmdbuf->bufsz < sizeof(uint64_t) + header.scratch.n_bufs * sizeof(buf_idx) ) {
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (header.scratch.reg >= 5) {
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
dev_priv->scratch_ages[header.scratch.reg] ++;
|
||||
|
||||
ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
|
||||
|
||||
cmdbuf->buf += sizeof(uint64_t);
|
||||
cmdbuf->bufsz -= sizeof(uint64_t);
|
||||
|
||||
for (i=0; i < header.scratch.n_bufs; i++) {
|
||||
buf_idx = *(u32 *)cmdbuf->buf;
|
||||
buf_idx *= 2; /* 8 bytes per buf */
|
||||
|
||||
if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
if (h_pending == 0) {
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
h_pending--;
|
||||
|
||||
if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
cmdbuf->buf += sizeof(buf_idx);
|
||||
cmdbuf->bufsz -= sizeof(buf_idx);
|
||||
}
|
||||
|
||||
BEGIN_RING(2);
|
||||
OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
|
||||
OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
|
||||
ADVANCE_RING();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and validates a user-supplied command buffer and emits appropriate
|
||||
* commands on the DMA ring buffer.
|
||||
* Called by the ioctl handler function radeon_cp_cmdbuf.
|
||||
*/
|
||||
int r300_do_cp_cmdbuf(drm_device_t *dev,
|
||||
DRMFILE filp,
|
||||
drm_file_t *filp_priv,
|
||||
drm_radeon_kcmd_buffer_t *cmdbuf)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_buf_t *buf = NULL;
|
||||
int emit_dispatch_age = 0;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* See the comment above r300_emit_begin3d for why this call must be here,
|
||||
* and what the cleanup gotos are for. */
|
||||
r300_pacify(dev_priv);
|
||||
|
||||
if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
|
||||
ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
|
||||
int idx;
|
||||
drm_r300_cmd_header_t header;
|
||||
|
||||
header.u = *(unsigned int *)cmdbuf->buf;
|
||||
|
||||
cmdbuf->buf += sizeof(header);
|
||||
cmdbuf->bufsz -= sizeof(header);
|
||||
|
||||
switch (header.header.cmd_type) {
|
||||
case R300_CMD_PACKET0:
|
||||
DRM_DEBUG("R300_CMD_PACKET0\n");
|
||||
ret = r300_emit_packet0(dev_priv, cmdbuf, header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_packet0 failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case R300_CMD_VPU:
|
||||
DRM_DEBUG("R300_CMD_VPU\n");
|
||||
ret = r300_emit_vpu(dev_priv, cmdbuf, header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_vpu failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case R300_CMD_PACKET3:
|
||||
DRM_DEBUG("R300_CMD_PACKET3\n");
|
||||
ret = r300_emit_packet3(dev_priv, cmdbuf, header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_emit_packet3 failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
case R300_CMD_END3D:
|
||||
DRM_DEBUG("R300_CMD_END3D\n");
|
||||
/* TODO:
|
||||
Ideally userspace driver should not need to issue this call,
|
||||
i.e. the drm driver should issue it automatically and prevent
|
||||
lockups.
|
||||
|
||||
In practice, we do not understand why this call is needed and what
|
||||
it does (except for some vague guesses that it has to do with cache
|
||||
coherence) and so the user space driver does it.
|
||||
|
||||
Once we are sure which uses prevent lockups the code could be moved
|
||||
into the kernel and the userspace driver will not
|
||||
need to use this command.
|
||||
|
||||
Note that issuing this command does not hurt anything
|
||||
except, possibly, performance */
|
||||
r300_pacify(dev_priv);
|
||||
break;
|
||||
|
||||
case R300_CMD_CP_DELAY:
|
||||
/* simple enough, we can do it here */
|
||||
DRM_DEBUG("R300_CMD_CP_DELAY\n");
|
||||
{
|
||||
int i;
|
||||
RING_LOCALS;
|
||||
|
||||
BEGIN_RING(header.delay.count);
|
||||
for (i = 0; i < header.delay.count; i++)
|
||||
OUT_RING(RADEON_CP_PACKET2);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
break;
|
||||
|
||||
case R300_CMD_DMA_DISCARD:
|
||||
DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
|
||||
idx = header.dma.buf_idx;
|
||||
if (idx < 0 || idx >= dma->buf_count) {
|
||||
DRM_ERROR("buffer index %d (of %d max)\n",
|
||||
idx, dma->buf_count - 1);
|
||||
ret = DRM_ERR(EINVAL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
buf = dma->buflist[idx];
|
||||
if (buf->filp != filp || buf->pending) {
|
||||
DRM_ERROR("bad buffer %p %p %d\n",
|
||||
buf->filp, filp, buf->pending);
|
||||
ret = DRM_ERR(EINVAL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
emit_dispatch_age = 1;
|
||||
r300_discard_buffer(dev, buf);
|
||||
break;
|
||||
|
||||
case R300_CMD_WAIT:
|
||||
/* simple enough, we can do it here */
|
||||
DRM_DEBUG("R300_CMD_WAIT\n");
|
||||
if (header.wait.flags == 0)
|
||||
break; /* nothing to do */
|
||||
|
||||
{
|
||||
RING_LOCALS;
|
||||
|
||||
BEGIN_RING(2);
|
||||
OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
|
||||
OUT_RING((header.wait.flags & 0xf) << 14);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
break;
|
||||
|
||||
case R300_CMD_SCRATCH:
|
||||
DRM_DEBUG("R300_CMD_SCRATCH\n");
|
||||
ret = r300_scratch(dev_priv, cmdbuf, header);
|
||||
if (ret) {
|
||||
DRM_ERROR("r300_scratch failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DRM_ERROR("bad cmd_type %i at %p\n",
|
||||
header.header.cmd_type,
|
||||
cmdbuf->buf - sizeof(header));
|
||||
ret = DRM_ERR(EINVAL);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG("END\n");
|
||||
|
||||
cleanup:
|
||||
r300_pacify(dev_priv);
|
||||
|
||||
/* We emit the vertex buffer age here, outside the pacifier "brackets"
|
||||
* for two reasons:
|
||||
* (1) This may coalesce multiple age emissions into a single one and
|
||||
* (2) more importantly, some chips lock up hard when scratch registers
|
||||
* are written inside the pacifier bracket.
|
||||
*/
|
||||
if (emit_dispatch_age) {
|
||||
RING_LOCALS;
|
||||
|
||||
/* Emit the vertex buffer age */
|
||||
BEGIN_RING(2);
|
||||
RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
COMMIT_RING();
|
||||
|
||||
return ret;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,730 @@
|
|||
/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*-
|
||||
*
|
||||
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
|
||||
* Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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:
|
||||
* Kevin E. Martin <martin@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/radeon_drm.h,v 1.14 2006/09/07 23:04:47 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __RADEON_DRM_H__
|
||||
#define __RADEON_DRM_H__
|
||||
|
||||
/* WARNING: If you change any of these defines, make sure to change the
|
||||
* defines in the X server file (radeon_sarea.h)
|
||||
*/
|
||||
#ifndef __RADEON_SAREA_DEFINES__
|
||||
#define __RADEON_SAREA_DEFINES__
|
||||
|
||||
/* Old style state flags, required for sarea interface (1.1 and 1.2
|
||||
* clears) and 1.2 drm_vertex2 ioctl.
|
||||
*/
|
||||
#define RADEON_UPLOAD_CONTEXT 0x00000001
|
||||
#define RADEON_UPLOAD_VERTFMT 0x00000002
|
||||
#define RADEON_UPLOAD_LINE 0x00000004
|
||||
#define RADEON_UPLOAD_BUMPMAP 0x00000008
|
||||
#define RADEON_UPLOAD_MASKS 0x00000010
|
||||
#define RADEON_UPLOAD_VIEWPORT 0x00000020
|
||||
#define RADEON_UPLOAD_SETUP 0x00000040
|
||||
#define RADEON_UPLOAD_TCL 0x00000080
|
||||
#define RADEON_UPLOAD_MISC 0x00000100
|
||||
#define RADEON_UPLOAD_TEX0 0x00000200
|
||||
#define RADEON_UPLOAD_TEX1 0x00000400
|
||||
#define RADEON_UPLOAD_TEX2 0x00000800
|
||||
#define RADEON_UPLOAD_TEX0IMAGES 0x00001000
|
||||
#define RADEON_UPLOAD_TEX1IMAGES 0x00002000
|
||||
#define RADEON_UPLOAD_TEX2IMAGES 0x00004000
|
||||
#define RADEON_UPLOAD_CLIPRECTS 0x00008000 /* handled client-side */
|
||||
#define RADEON_REQUIRE_QUIESCENCE 0x00010000
|
||||
#define RADEON_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */
|
||||
#define RADEON_UPLOAD_ALL 0x003effff
|
||||
#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff
|
||||
|
||||
/* New style per-packet identifiers for use in cmd_buffer ioctl with
|
||||
* the RADEON_EMIT_PACKET command. Comments relate new packets to old
|
||||
* state bits and the packet size:
|
||||
*/
|
||||
#define RADEON_EMIT_PP_MISC 0 /* context/7 */
|
||||
#define RADEON_EMIT_PP_CNTL 1 /* context/3 */
|
||||
#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */
|
||||
#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */
|
||||
#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */
|
||||
#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */
|
||||
#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */
|
||||
#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */
|
||||
#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */
|
||||
#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */
|
||||
#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */
|
||||
#define RADEON_EMIT_RE_MISC 11 /* misc/1 */
|
||||
#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */
|
||||
#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */
|
||||
#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */
|
||||
#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */
|
||||
#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */
|
||||
#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */
|
||||
#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */
|
||||
#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */
|
||||
#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */
|
||||
#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */
|
||||
#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */
|
||||
#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */
|
||||
#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */
|
||||
#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */
|
||||
#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */
|
||||
#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */
|
||||
#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */
|
||||
#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */
|
||||
#define R200_EMIT_TFACTOR_0 30 /* tf/7 */
|
||||
#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */
|
||||
#define R200_EMIT_VAP_CTL 32 /* vap/1 */
|
||||
#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */
|
||||
#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */
|
||||
#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */
|
||||
#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */
|
||||
#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */
|
||||
#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */
|
||||
#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */
|
||||
#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */
|
||||
#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */
|
||||
#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */
|
||||
#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */
|
||||
#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */
|
||||
#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */
|
||||
#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */
|
||||
#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */
|
||||
#define R200_EMIT_VTE_CNTL 48 /* vte/1 */
|
||||
#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */
|
||||
#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */
|
||||
#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */
|
||||
#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */
|
||||
#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */
|
||||
#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */
|
||||
#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */
|
||||
#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */
|
||||
#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */
|
||||
#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */
|
||||
#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */
|
||||
#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */
|
||||
#define R200_EMIT_PP_CUBIC_FACES_0 61
|
||||
#define R200_EMIT_PP_CUBIC_OFFSETS_0 62
|
||||
#define R200_EMIT_PP_CUBIC_FACES_1 63
|
||||
#define R200_EMIT_PP_CUBIC_OFFSETS_1 64
|
||||
#define R200_EMIT_PP_CUBIC_FACES_2 65
|
||||
#define R200_EMIT_PP_CUBIC_OFFSETS_2 66
|
||||
#define R200_EMIT_PP_CUBIC_FACES_3 67
|
||||
#define R200_EMIT_PP_CUBIC_OFFSETS_3 68
|
||||
#define R200_EMIT_PP_CUBIC_FACES_4 69
|
||||
#define R200_EMIT_PP_CUBIC_OFFSETS_4 70
|
||||
#define R200_EMIT_PP_CUBIC_FACES_5 71
|
||||
#define R200_EMIT_PP_CUBIC_OFFSETS_5 72
|
||||
#define RADEON_EMIT_PP_TEX_SIZE_0 73
|
||||
#define RADEON_EMIT_PP_TEX_SIZE_1 74
|
||||
#define RADEON_EMIT_PP_TEX_SIZE_2 75
|
||||
#define R200_EMIT_RB3D_BLENDCOLOR 76
|
||||
#define R200_EMIT_TCL_POINT_SPRITE_CNTL 77
|
||||
#define RADEON_EMIT_PP_CUBIC_FACES_0 78
|
||||
#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0 79
|
||||
#define RADEON_EMIT_PP_CUBIC_FACES_1 80
|
||||
#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1 81
|
||||
#define RADEON_EMIT_PP_CUBIC_FACES_2 82
|
||||
#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83
|
||||
#define R200_EMIT_PP_TRI_PERF_CNTL 84
|
||||
#define R200_EMIT_PP_AFS_0 85
|
||||
#define R200_EMIT_PP_AFS_1 86
|
||||
#define R200_EMIT_ATF_TFACTOR 87
|
||||
#define R200_EMIT_PP_TXCTLALL_0 88
|
||||
#define R200_EMIT_PP_TXCTLALL_1 89
|
||||
#define R200_EMIT_PP_TXCTLALL_2 90
|
||||
#define R200_EMIT_PP_TXCTLALL_3 91
|
||||
#define R200_EMIT_PP_TXCTLALL_4 92
|
||||
#define R200_EMIT_PP_TXCTLALL_5 93
|
||||
#define R200_EMIT_VAP_PVS_CNTL 94
|
||||
#define RADEON_MAX_STATE_PACKETS 95
|
||||
|
||||
/* Commands understood by cmd_buffer ioctl. More can be added but
|
||||
* obviously these can't be removed or changed:
|
||||
*/
|
||||
#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */
|
||||
#define RADEON_CMD_SCALARS 2 /* emit scalar data */
|
||||
#define RADEON_CMD_VECTORS 3 /* emit vector data */
|
||||
#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
|
||||
#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 */
|
||||
#define RADEON_CMD_VECLINEAR 9 /* another r200 stopgap */
|
||||
|
||||
typedef union {
|
||||
int i;
|
||||
struct {
|
||||
unsigned char cmd_type, pad0, pad1, pad2;
|
||||
} header;
|
||||
struct {
|
||||
unsigned char cmd_type, packet_id, pad0, pad1;
|
||||
} packet;
|
||||
struct {
|
||||
unsigned char cmd_type, offset, stride, count;
|
||||
} scalars;
|
||||
struct {
|
||||
unsigned char cmd_type, offset, stride, count;
|
||||
} vectors;
|
||||
struct {
|
||||
unsigned char cmd_type, addr_lo, addr_hi, count;
|
||||
} veclinear;
|
||||
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
|
||||
|
||||
/* Allowed parameters for R300_CMD_PACKET3
|
||||
*/
|
||||
#define R300_CMD_PACKET3_CLEAR 0
|
||||
#define R300_CMD_PACKET3_RAW 1
|
||||
|
||||
/* Commands understood by cmd_buffer ioctl for R300.
|
||||
* The interface has not been stabilized, so some of these may be removed
|
||||
* and eventually reordered before stabilization.
|
||||
*/
|
||||
#define R300_CMD_PACKET0 1
|
||||
#define R300_CMD_VPU 2 /* emit vertex program upload */
|
||||
#define R300_CMD_PACKET3 3 /* emit a packet3 */
|
||||
#define R300_CMD_END3D 4 /* emit sequence ending 3d rendering */
|
||||
#define R300_CMD_CP_DELAY 5
|
||||
#define R300_CMD_DMA_DISCARD 6
|
||||
#define R300_CMD_WAIT 7
|
||||
# define R300_WAIT_2D 0x1
|
||||
# define R300_WAIT_3D 0x2
|
||||
# define R300_WAIT_2D_CLEAN 0x3
|
||||
# define R300_WAIT_3D_CLEAN 0x4
|
||||
#define R300_CMD_SCRATCH 8
|
||||
|
||||
typedef union {
|
||||
unsigned int u;
|
||||
struct {
|
||||
unsigned char cmd_type, pad0, pad1, pad2;
|
||||
} header;
|
||||
struct {
|
||||
unsigned char cmd_type, count, reglo, reghi;
|
||||
} packet0;
|
||||
struct {
|
||||
unsigned char cmd_type, count, adrlo, adrhi;
|
||||
} vpu;
|
||||
struct {
|
||||
unsigned char cmd_type, packet, pad0, pad1;
|
||||
} packet3;
|
||||
struct {
|
||||
unsigned char cmd_type, packet;
|
||||
unsigned short count; /* amount of packet2 to emit */
|
||||
} delay;
|
||||
struct {
|
||||
unsigned char cmd_type, buf_idx, pad0, pad1;
|
||||
} dma;
|
||||
struct {
|
||||
unsigned char cmd_type, flags, pad0, pad1;
|
||||
} wait;
|
||||
struct {
|
||||
unsigned char cmd_type, reg, n_bufs, flags;
|
||||
} scratch;
|
||||
} drm_r300_cmd_header_t;
|
||||
|
||||
#define RADEON_FRONT 0x1
|
||||
#define RADEON_BACK 0x2
|
||||
#define RADEON_DEPTH 0x4
|
||||
#define RADEON_STENCIL 0x8
|
||||
#define RADEON_CLEAR_FASTZ 0x80000000
|
||||
#define RADEON_USE_HIERZ 0x40000000
|
||||
#define RADEON_USE_COMP_ZBUF 0x20000000
|
||||
|
||||
/* Primitive types
|
||||
*/
|
||||
#define RADEON_POINTS 0x1
|
||||
#define RADEON_LINES 0x2
|
||||
#define RADEON_LINE_STRIP 0x3
|
||||
#define RADEON_TRIANGLES 0x4
|
||||
#define RADEON_TRIANGLE_FAN 0x5
|
||||
#define RADEON_TRIANGLE_STRIP 0x6
|
||||
|
||||
/* Vertex/indirect buffer size
|
||||
*/
|
||||
#define RADEON_BUFFER_SIZE 65536
|
||||
|
||||
/* Byte offsets for indirect buffer data
|
||||
*/
|
||||
#define RADEON_INDEX_PRIM_OFFSET 20
|
||||
|
||||
#define RADEON_SCRATCH_REG_OFFSET 32
|
||||
|
||||
#define RADEON_NR_SAREA_CLIPRECTS 12
|
||||
|
||||
/* There are 2 heaps (local/GART). Each region within a heap is a
|
||||
* minimum of 64k, and there are at most 64 of them per heap.
|
||||
*/
|
||||
#define RADEON_LOCAL_TEX_HEAP 0
|
||||
#define RADEON_GART_TEX_HEAP 1
|
||||
#define RADEON_NR_TEX_HEAPS 2
|
||||
#define RADEON_NR_TEX_REGIONS 64
|
||||
#define RADEON_LOG_TEX_GRANULARITY 16
|
||||
|
||||
#define RADEON_MAX_TEXTURE_LEVELS 12
|
||||
#define RADEON_MAX_TEXTURE_UNITS 3
|
||||
|
||||
#define RADEON_MAX_SURFACES 8
|
||||
|
||||
/* Blits have strict offset rules. All blit offset must be aligned on
|
||||
* a 1K-byte boundary.
|
||||
*/
|
||||
#define RADEON_OFFSET_SHIFT 10
|
||||
#define RADEON_OFFSET_ALIGN (1 << RADEON_OFFSET_SHIFT)
|
||||
#define RADEON_OFFSET_MASK (RADEON_OFFSET_ALIGN - 1)
|
||||
|
||||
#endif /* __RADEON_SAREA_DEFINES__ */
|
||||
|
||||
typedef struct {
|
||||
unsigned int red;
|
||||
unsigned int green;
|
||||
unsigned int blue;
|
||||
unsigned int alpha;
|
||||
} radeon_color_regs_t;
|
||||
|
||||
typedef struct {
|
||||
/* Context state */
|
||||
unsigned int pp_misc; /* 0x1c14 */
|
||||
unsigned int pp_fog_color;
|
||||
unsigned int re_solid_color;
|
||||
unsigned int rb3d_blendcntl;
|
||||
unsigned int rb3d_depthoffset;
|
||||
unsigned int rb3d_depthpitch;
|
||||
unsigned int rb3d_zstencilcntl;
|
||||
|
||||
unsigned int pp_cntl; /* 0x1c38 */
|
||||
unsigned int rb3d_cntl;
|
||||
unsigned int rb3d_coloroffset;
|
||||
unsigned int re_width_height;
|
||||
unsigned int rb3d_colorpitch;
|
||||
unsigned int se_cntl;
|
||||
|
||||
/* Vertex format state */
|
||||
unsigned int se_coord_fmt; /* 0x1c50 */
|
||||
|
||||
/* Line state */
|
||||
unsigned int re_line_pattern; /* 0x1cd0 */
|
||||
unsigned int re_line_state;
|
||||
|
||||
unsigned int se_line_width; /* 0x1db8 */
|
||||
|
||||
/* Bumpmap state */
|
||||
unsigned int pp_lum_matrix; /* 0x1d00 */
|
||||
|
||||
unsigned int pp_rot_matrix_0; /* 0x1d58 */
|
||||
unsigned int pp_rot_matrix_1;
|
||||
|
||||
/* Mask state */
|
||||
unsigned int rb3d_stencilrefmask; /* 0x1d7c */
|
||||
unsigned int rb3d_ropcntl;
|
||||
unsigned int rb3d_planemask;
|
||||
|
||||
/* Viewport state */
|
||||
unsigned int se_vport_xscale; /* 0x1d98 */
|
||||
unsigned int se_vport_xoffset;
|
||||
unsigned int se_vport_yscale;
|
||||
unsigned int se_vport_yoffset;
|
||||
unsigned int se_vport_zscale;
|
||||
unsigned int se_vport_zoffset;
|
||||
|
||||
/* Setup state */
|
||||
unsigned int se_cntl_status; /* 0x2140 */
|
||||
|
||||
/* Misc state */
|
||||
unsigned int re_top_left; /* 0x26c0 */
|
||||
unsigned int re_misc;
|
||||
} drm_radeon_context_regs_t;
|
||||
|
||||
typedef struct {
|
||||
/* Zbias state */
|
||||
unsigned int se_zbias_factor; /* 0x1dac */
|
||||
unsigned int se_zbias_constant;
|
||||
} drm_radeon_context2_regs_t;
|
||||
|
||||
/* Setup registers for each texture unit
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int pp_txfilter;
|
||||
unsigned int pp_txformat;
|
||||
unsigned int pp_txoffset;
|
||||
unsigned int pp_txcblend;
|
||||
unsigned int pp_txablend;
|
||||
unsigned int pp_tfactor;
|
||||
unsigned int pp_border_color;
|
||||
} drm_radeon_texture_regs_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int start;
|
||||
unsigned int finish;
|
||||
unsigned int prim:8;
|
||||
unsigned int stateidx:8;
|
||||
unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
|
||||
unsigned int vc_format; /* vertex format */
|
||||
} drm_radeon_prim_t;
|
||||
|
||||
typedef struct {
|
||||
drm_radeon_context_regs_t context;
|
||||
drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
|
||||
drm_radeon_context2_regs_t context2;
|
||||
unsigned int dirty;
|
||||
} drm_radeon_state_t;
|
||||
|
||||
typedef struct {
|
||||
/* The channel for communication of state information to the
|
||||
* kernel on firing a vertex buffer with either of the
|
||||
* obsoleted vertex/index ioctls.
|
||||
*/
|
||||
drm_radeon_context_regs_t context_state;
|
||||
drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS];
|
||||
unsigned int dirty;
|
||||
unsigned int vertsize;
|
||||
unsigned int vc_format;
|
||||
|
||||
/* The current cliprects, or a subset thereof.
|
||||
*/
|
||||
drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
|
||||
unsigned int nbox;
|
||||
|
||||
/* Counters for client-side throttling of rendering clients.
|
||||
*/
|
||||
unsigned int last_frame;
|
||||
unsigned int last_dispatch;
|
||||
unsigned int last_clear;
|
||||
|
||||
drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
|
||||
1];
|
||||
unsigned int tex_age[RADEON_NR_TEX_HEAPS];
|
||||
int ctx_owner;
|
||||
int pfState; /* number of 3d windows (0,1,2ormore) */
|
||||
int pfCurrentPage; /* which buffer is being displayed? */
|
||||
int crtc2_base; /* CRTC2 frame offset */
|
||||
int tiling_enabled; /* set by drm, read by 2d + 3d clients */
|
||||
} drm_radeon_sarea_t;
|
||||
|
||||
/* WARNING: If you change any of these defines, make sure to change the
|
||||
* defines in the Xserver file (xf86drmRadeon.h)
|
||||
*
|
||||
* KW: actually it's illegal to change any of this (backwards compatibility).
|
||||
*/
|
||||
|
||||
/* Radeon specific ioctls
|
||||
* The device specific ioctl range is 0x40 to 0x79.
|
||||
*/
|
||||
#define DRM_RADEON_CP_INIT 0x00
|
||||
#define DRM_RADEON_CP_START 0x01
|
||||
#define DRM_RADEON_CP_STOP 0x02
|
||||
#define DRM_RADEON_CP_RESET 0x03
|
||||
#define DRM_RADEON_CP_IDLE 0x04
|
||||
#define DRM_RADEON_RESET 0x05
|
||||
#define DRM_RADEON_FULLSCREEN 0x06
|
||||
#define DRM_RADEON_SWAP 0x07
|
||||
#define DRM_RADEON_CLEAR 0x08
|
||||
#define DRM_RADEON_VERTEX 0x09
|
||||
#define DRM_RADEON_INDICES 0x0A
|
||||
#define DRM_RADEON_NOT_USED
|
||||
#define DRM_RADEON_STIPPLE 0x0C
|
||||
#define DRM_RADEON_INDIRECT 0x0D
|
||||
#define DRM_RADEON_TEXTURE 0x0E
|
||||
#define DRM_RADEON_VERTEX2 0x0F
|
||||
#define DRM_RADEON_CMDBUF 0x10
|
||||
#define DRM_RADEON_GETPARAM 0x11
|
||||
#define DRM_RADEON_FLIP 0x12
|
||||
#define DRM_RADEON_ALLOC 0x13
|
||||
#define DRM_RADEON_FREE 0x14
|
||||
#define DRM_RADEON_INIT_HEAP 0x15
|
||||
#define DRM_RADEON_IRQ_EMIT 0x16
|
||||
#define DRM_RADEON_IRQ_WAIT 0x17
|
||||
#define DRM_RADEON_CP_RESUME 0x18
|
||||
#define DRM_RADEON_SETPARAM 0x19
|
||||
#define DRM_RADEON_SURF_ALLOC 0x1a
|
||||
#define DRM_RADEON_SURF_FREE 0x1b
|
||||
|
||||
#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
|
||||
#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START)
|
||||
#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t)
|
||||
#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESET)
|
||||
#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE)
|
||||
#define DRM_IOCTL_RADEON_RESET DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_RESET)
|
||||
#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t)
|
||||
#define DRM_IOCTL_RADEON_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_SWAP)
|
||||
#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t)
|
||||
#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t)
|
||||
#define DRM_IOCTL_RADEON_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t)
|
||||
#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t)
|
||||
#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t)
|
||||
#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t)
|
||||
#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t)
|
||||
#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t)
|
||||
#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t)
|
||||
#define DRM_IOCTL_RADEON_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_FLIP)
|
||||
#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t)
|
||||
#define DRM_IOCTL_RADEON_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t)
|
||||
#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t)
|
||||
#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t)
|
||||
#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t)
|
||||
#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME)
|
||||
#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
|
||||
#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
|
||||
#define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
|
||||
|
||||
typedef struct drm_radeon_init {
|
||||
enum {
|
||||
RADEON_INIT_CP = 0x01,
|
||||
RADEON_CLEANUP_CP = 0x02,
|
||||
RADEON_INIT_R200_CP = 0x03,
|
||||
RADEON_INIT_R300_CP = 0x04
|
||||
} func;
|
||||
unsigned long sarea_priv_offset;
|
||||
int is_pci; /* for overriding only */
|
||||
int cp_mode;
|
||||
int gart_size;
|
||||
int ring_size;
|
||||
int usec_timeout;
|
||||
|
||||
unsigned int fb_bpp;
|
||||
unsigned int front_offset, front_pitch;
|
||||
unsigned int back_offset, back_pitch;
|
||||
unsigned int depth_bpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
|
||||
unsigned long fb_offset DEPRECATED; /* deprecated, driver asks hardware */
|
||||
unsigned long mmio_offset DEPRECATED; /* deprecated, driver asks hardware */
|
||||
unsigned long ring_offset;
|
||||
unsigned long ring_rptr_offset;
|
||||
unsigned long buffers_offset;
|
||||
unsigned long gart_textures_offset;
|
||||
} drm_radeon_init_t;
|
||||
|
||||
typedef struct drm_radeon_cp_stop {
|
||||
int flush;
|
||||
int idle;
|
||||
} drm_radeon_cp_stop_t;
|
||||
|
||||
typedef struct drm_radeon_fullscreen {
|
||||
enum {
|
||||
RADEON_INIT_FULLSCREEN = 0x01,
|
||||
RADEON_CLEANUP_FULLSCREEN = 0x02
|
||||
} func;
|
||||
} drm_radeon_fullscreen_t;
|
||||
|
||||
#define CLEAR_X1 0
|
||||
#define CLEAR_Y1 1
|
||||
#define CLEAR_X2 2
|
||||
#define CLEAR_Y2 3
|
||||
#define CLEAR_DEPTH 4
|
||||
|
||||
typedef union drm_radeon_clear_rect {
|
||||
float f[5];
|
||||
unsigned int ui[5];
|
||||
} drm_radeon_clear_rect_t;
|
||||
|
||||
typedef struct drm_radeon_clear {
|
||||
unsigned int flags;
|
||||
unsigned int clear_color;
|
||||
unsigned int clear_depth;
|
||||
unsigned int color_mask;
|
||||
unsigned int depth_mask; /* misnamed field: should be stencil */
|
||||
drm_radeon_clear_rect_t __user *depth_boxes;
|
||||
} drm_radeon_clear_t;
|
||||
|
||||
typedef struct drm_radeon_vertex {
|
||||
int prim;
|
||||
int idx; /* Index of vertex buffer */
|
||||
int count; /* Number of vertices in buffer */
|
||||
int discard; /* Client finished with buffer? */
|
||||
} drm_radeon_vertex_t;
|
||||
|
||||
typedef struct drm_radeon_indices {
|
||||
int prim;
|
||||
int idx;
|
||||
int start;
|
||||
int end;
|
||||
int discard; /* Client finished with buffer? */
|
||||
} drm_radeon_indices_t;
|
||||
|
||||
/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices
|
||||
* - allows multiple primitives and state changes in a single ioctl
|
||||
* - supports driver change to emit native primitives
|
||||
*/
|
||||
typedef struct drm_radeon_vertex2 {
|
||||
int idx; /* Index of vertex buffer */
|
||||
int discard; /* Client finished with buffer? */
|
||||
int nr_states;
|
||||
drm_radeon_state_t __user *state;
|
||||
int nr_prims;
|
||||
drm_radeon_prim_t __user *prim;
|
||||
} drm_radeon_vertex2_t;
|
||||
|
||||
/* v1.3 - obsoletes drm_radeon_vertex2
|
||||
* - allows arbitarily large cliprect list
|
||||
* - allows updating of tcl packet, vector and scalar state
|
||||
* - allows memory-efficient description of state updates
|
||||
* - allows state to be emitted without a primitive
|
||||
* (for clears, ctx switches)
|
||||
* - allows more than one dma buffer to be referenced per ioctl
|
||||
* - supports tcl driver
|
||||
* - may be extended in future versions with new cmd types, packets
|
||||
*/
|
||||
typedef struct drm_radeon_cmd_buffer {
|
||||
int bufsz;
|
||||
char __user *buf;
|
||||
int nbox;
|
||||
drm_clip_rect_t __user *boxes;
|
||||
} drm_radeon_cmd_buffer_t;
|
||||
|
||||
typedef struct drm_radeon_tex_image {
|
||||
unsigned int x, y; /* Blit coordinates */
|
||||
unsigned int width, height;
|
||||
const void __user *data;
|
||||
} drm_radeon_tex_image_t;
|
||||
|
||||
typedef struct drm_radeon_texture {
|
||||
unsigned int offset;
|
||||
int pitch;
|
||||
int format;
|
||||
int width; /* Texture image coordinates */
|
||||
int height;
|
||||
drm_radeon_tex_image_t __user *image;
|
||||
} drm_radeon_texture_t;
|
||||
|
||||
typedef struct drm_radeon_stipple {
|
||||
unsigned int __user *mask;
|
||||
} drm_radeon_stipple_t;
|
||||
|
||||
typedef struct drm_radeon_indirect {
|
||||
int idx;
|
||||
int start;
|
||||
int end;
|
||||
int discard;
|
||||
} drm_radeon_indirect_t;
|
||||
|
||||
/* enum for card type parameters */
|
||||
#define RADEON_CARD_PCI 0
|
||||
#define RADEON_CARD_AGP 1
|
||||
#define RADEON_CARD_PCIE 2
|
||||
|
||||
/* 1.3: An ioctl to get parameters that aren't available to the 3d
|
||||
* client any other way.
|
||||
*/
|
||||
#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */
|
||||
#define RADEON_PARAM_LAST_FRAME 2
|
||||
#define RADEON_PARAM_LAST_DISPATCH 3
|
||||
#define RADEON_PARAM_LAST_CLEAR 4
|
||||
/* Added with DRM version 1.6. */
|
||||
#define RADEON_PARAM_IRQ_NR 5
|
||||
#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */
|
||||
/* Added with DRM version 1.8. */
|
||||
#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */
|
||||
#define RADEON_PARAM_STATUS_HANDLE 8
|
||||
#define RADEON_PARAM_SAREA_HANDLE 9
|
||||
#define RADEON_PARAM_GART_TEX_HANDLE 10
|
||||
#define RADEON_PARAM_SCRATCH_OFFSET 11
|
||||
#define RADEON_PARAM_CARD_TYPE 12
|
||||
|
||||
typedef struct drm_radeon_getparam {
|
||||
int param;
|
||||
void __user *value;
|
||||
} drm_radeon_getparam_t;
|
||||
|
||||
/* 1.6: Set up a memory manager for regions of shared memory:
|
||||
*/
|
||||
#define RADEON_MEM_REGION_GART 1
|
||||
#define RADEON_MEM_REGION_FB 2
|
||||
|
||||
typedef struct drm_radeon_mem_alloc {
|
||||
int region;
|
||||
int alignment;
|
||||
int size;
|
||||
int __user *region_offset; /* offset from start of fb or GART */
|
||||
} 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 __user *irq_seq;
|
||||
} drm_radeon_irq_emit_t;
|
||||
|
||||
typedef struct drm_radeon_irq_wait {
|
||||
int irq_seq;
|
||||
} drm_radeon_irq_wait_t;
|
||||
|
||||
/* 1.10: Clients tell the DRM where they think the framebuffer is located in
|
||||
* the card's address space, via a new generic ioctl to set parameters
|
||||
*/
|
||||
|
||||
typedef struct drm_radeon_setparam {
|
||||
unsigned int param;
|
||||
int64_t value;
|
||||
} drm_radeon_setparam_t;
|
||||
|
||||
#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
|
||||
#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
|
||||
#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
|
||||
|
||||
#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
|
||||
|
||||
/* 1.14: Clients can allocate/free a surface
|
||||
*/
|
||||
typedef struct drm_radeon_surface_alloc {
|
||||
unsigned int address;
|
||||
unsigned int size;
|
||||
unsigned int flags;
|
||||
} drm_radeon_surface_alloc_t;
|
||||
|
||||
typedef struct drm_radeon_surface_free {
|
||||
unsigned int address;
|
||||
} drm_radeon_surface_free_t;
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,148 @@
|
|||
/* radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
|
||||
* Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/radeon_drv.c,v 1.14 2005/12/20 22:44:36 jhb Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
int radeon_no_wb;
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t radeon_pciidlist[] = {
|
||||
radeon_PCI_IDS
|
||||
};
|
||||
|
||||
static void radeon_configure(drm_device_t *dev)
|
||||
{
|
||||
dev->driver.buf_priv_size = sizeof(drm_radeon_buf_priv_t);
|
||||
dev->driver.load = radeon_driver_load;
|
||||
dev->driver.unload = radeon_driver_unload;
|
||||
dev->driver.firstopen = radeon_driver_firstopen;
|
||||
dev->driver.open = radeon_driver_open;
|
||||
dev->driver.preclose = radeon_driver_preclose;
|
||||
dev->driver.postclose = radeon_driver_postclose;
|
||||
dev->driver.lastclose = radeon_driver_lastclose;
|
||||
dev->driver.vblank_wait = radeon_driver_vblank_wait;
|
||||
dev->driver.irq_preinstall = radeon_driver_irq_preinstall;
|
||||
dev->driver.irq_postinstall = radeon_driver_irq_postinstall;
|
||||
dev->driver.irq_uninstall = radeon_driver_irq_uninstall;
|
||||
dev->driver.irq_handler = radeon_driver_irq_handler;
|
||||
dev->driver.dma_ioctl = radeon_cp_buffers;
|
||||
|
||||
dev->driver.ioctls = radeon_ioctls;
|
||||
dev->driver.max_ioctl = radeon_max_ioctl;
|
||||
|
||||
dev->driver.name = DRIVER_NAME;
|
||||
dev->driver.desc = DRIVER_DESC;
|
||||
dev->driver.date = DRIVER_DATE;
|
||||
dev->driver.major = DRIVER_MAJOR;
|
||||
dev->driver.minor = DRIVER_MINOR;
|
||||
dev->driver.patchlevel = DRIVER_PATCHLEVEL;
|
||||
|
||||
dev->driver.use_agp = 1;
|
||||
dev->driver.use_mtrr = 1;
|
||||
dev->driver.use_pci_dma = 1;
|
||||
dev->driver.use_sg = 1;
|
||||
dev->driver.use_dma = 1;
|
||||
dev->driver.use_irq = 1;
|
||||
dev->driver.use_vbl_irq = 1;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
radeon_probe(device_t dev)
|
||||
{
|
||||
return drm_probe(dev, radeon_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
radeon_attach(device_t nbdev)
|
||||
{
|
||||
drm_device_t *dev = device_get_softc(nbdev);
|
||||
|
||||
bzero(dev, sizeof(drm_device_t));
|
||||
radeon_configure(dev);
|
||||
return drm_attach(nbdev, radeon_pciidlist);
|
||||
}
|
||||
|
||||
static device_method_t radeon_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, radeon_probe),
|
||||
DEVMETHOD(device_attach, radeon_attach),
|
||||
DEVMETHOD(device_detach, drm_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t radeon_driver = {
|
||||
"drm",
|
||||
radeon_methods,
|
||||
sizeof(drm_device_t)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(radeon, vgapci, radeon_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(radeon, pci, radeon_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(radeon, drm, 1, 1, 1);
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
static int
|
||||
radeondrm_probe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
return drm_probe(pa, radeon_pciidlist);
|
||||
}
|
||||
|
||||
static void
|
||||
radeondrm_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
drm_device_t *dev = (drm_device_t *)self;
|
||||
|
||||
radeon_configure(dev);
|
||||
return drm_attach(self, pa, radeon_pciidlist);
|
||||
}
|
||||
|
||||
CFATTACH_DECL(radeondrm, sizeof(drm_device_t), radeondrm_probe, radeondrm_attach,
|
||||
drm_detach, drm_activate);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,249 @@
|
|||
/* radeon_irq.c -- IRQ handling 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>
|
||||
* Michel D<EFBFBD>zer <michel@daenzer.net>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/radeon_irq.c,v 1.7 2005/11/28 23:13:54 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
|
||||
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
|
||||
u32 mask)
|
||||
{
|
||||
u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
|
||||
if (irqs)
|
||||
RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
|
||||
return irqs;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
irqreturn_t radeon_driver_irq_handler(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 stat;
|
||||
|
||||
/* Only consider the bits we're interested in - others could be used
|
||||
* outside the DRM
|
||||
*/
|
||||
stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
|
||||
RADEON_CRTC_VBLANK_STAT));
|
||||
if (!stat)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* SW interrupt */
|
||||
if (stat & RADEON_SW_INT_TEST) {
|
||||
DRM_WAKEUP(&dev_priv->swi_queue);
|
||||
}
|
||||
|
||||
/* VBLANK interrupt */
|
||||
if (stat & RADEON_CRTC_VBLANK_STAT) {
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int radeon_emit_irq(drm_device_t * dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
unsigned int ret;
|
||||
RING_LOCALS;
|
||||
|
||||
atomic_inc(&dev_priv->swi_emitted);
|
||||
ret = atomic_read(&dev_priv->swi_emitted);
|
||||
|
||||
BEGIN_RING(4);
|
||||
OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
|
||||
OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
|
||||
ADVANCE_RING();
|
||||
COMMIT_RING();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
|
||||
return 0;
|
||||
|
||||
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
|
||||
|
||||
DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
|
||||
RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
|
||||
radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
|
||||
|
||||
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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, filp);
|
||||
|
||||
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 __user *) 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 __user *) data,
|
||||
sizeof(irqwait));
|
||||
|
||||
return radeon_wait_irq(dev, irqwait.irq_seq);
|
||||
}
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void radeon_driver_irq_preinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
|
||||
/* Disable *all* interrupts */
|
||||
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
|
||||
|
||||
/* Clear bits if they're already high */
|
||||
radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
|
||||
RADEON_CRTC_VBLANK_STAT));
|
||||
}
|
||||
|
||||
void radeon_driver_irq_postinstall(drm_device_t * dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
|
||||
atomic_set(&dev_priv->swi_emitted, 0);
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
|
||||
|
||||
/* Turn on SW and VBL ints */
|
||||
RADEON_WRITE(RADEON_GEN_INT_CNTL,
|
||||
RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
|
||||
}
|
||||
|
||||
void radeon_driver_irq_uninstall(drm_device_t * dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
/* Disable *all* interrupts */
|
||||
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
|
||||
}
|
|
@ -0,0 +1,319 @@
|
|||
/* radeon_mem.c -- Simple GART/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 <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/radeon_mem.c,v 1.8 2005/11/28 23:13:54 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
|
||||
/* Very simple allocator for GART 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,
|
||||
DRMFILE filp)
|
||||
{
|
||||
/* Maybe cut off the start of an existing block */
|
||||
if (start > p->start) {
|
||||
struct mem_block *newblock =
|
||||
drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
|
||||
if (!newblock)
|
||||
goto out;
|
||||
newblock->start = start;
|
||||
newblock->size = p->size - (start - p->start);
|
||||
newblock->filp = NULL;
|
||||
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_alloc(sizeof(*newblock), DRM_MEM_BUFS);
|
||||
if (!newblock)
|
||||
goto out;
|
||||
newblock->start = start + size;
|
||||
newblock->size = p->size - size;
|
||||
newblock->filp = NULL;
|
||||
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->filp = filp;
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct mem_block *alloc_block(struct mem_block *heap, int size,
|
||||
int align2, DRMFILE filp)
|
||||
{
|
||||
struct mem_block *p;
|
||||
int mask = (1 << align2) - 1;
|
||||
|
||||
list_for_each(p, heap) {
|
||||
int start = (p->start + mask) & ~mask;
|
||||
if (p->filp == 0 && start + size <= p->start + p->size)
|
||||
return split_block(p, start, size, filp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct mem_block *find_block(struct mem_block *heap, int start)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
list_for_each(p, heap)
|
||||
if (p->start == start)
|
||||
return p;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void free_block(struct mem_block *p)
|
||||
{
|
||||
p->filp = NULL;
|
||||
|
||||
/* Assumes a single contiguous range. Needs a special filp in
|
||||
* 'heap' to stop it being subsumed.
|
||||
*/
|
||||
if (p->next->filp == 0) {
|
||||
struct mem_block *q = p->next;
|
||||
p->size += q->size;
|
||||
p->next = q->next;
|
||||
p->next->prev = p;
|
||||
drm_free(q, sizeof(*q), DRM_MEM_BUFS);
|
||||
}
|
||||
|
||||
if (p->prev->filp == 0) {
|
||||
struct mem_block *q = p->prev;
|
||||
q->size += p->size;
|
||||
q->next = p->next;
|
||||
q->next->prev = q;
|
||||
drm_free(p, sizeof(*q), DRM_MEM_BUFS);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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_alloc(sizeof(*blocks), DRM_MEM_BUFS);
|
||||
|
||||
if (!blocks)
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
||||
*heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
|
||||
if (!*heap) {
|
||||
drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
|
||||
blocks->start = start;
|
||||
blocks->size = size;
|
||||
blocks->filp = NULL;
|
||||
blocks->next = blocks->prev = *heap;
|
||||
|
||||
memset(*heap, 0, sizeof(**heap));
|
||||
(*heap)->filp = (DRMFILE) - 1;
|
||||
(*heap)->next = (*heap)->prev = blocks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free all blocks associated with the releasing file.
|
||||
*/
|
||||
void radeon_mem_release(DRMFILE filp, struct mem_block *heap)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
if (!heap || !heap->next)
|
||||
return;
|
||||
|
||||
list_for_each(p, heap) {
|
||||
if (p->filp == filp)
|
||||
p->filp = NULL;
|
||||
}
|
||||
|
||||
/* Assumes a single contiguous range. Needs a special filp in
|
||||
* 'heap' to stop it being subsumed.
|
||||
*/
|
||||
list_for_each(p, heap) {
|
||||
while (p->filp == 0 && p->next->filp == 0) {
|
||||
struct mem_block *q = p->next;
|
||||
p->size += q->size;
|
||||
p->next = q->next;
|
||||
p->next->prev = p;
|
||||
drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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, sizeof(*q), DRM_MEM_DRIVER);
|
||||
}
|
||||
|
||||
drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER);
|
||||
*heap = NULL;
|
||||
}
|
||||
|
||||
/* IOCTL HANDLERS */
|
||||
|
||||
static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region)
|
||||
{
|
||||
switch (region) {
|
||||
case RADEON_MEM_REGION_GART:
|
||||
return &dev_priv->gart_heap;
|
||||
case RADEON_MEM_REGION_FB:
|
||||
return &dev_priv->fb_heap;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 __user *) 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, filp);
|
||||
|
||||
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 __user *) 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->filp != filp)
|
||||
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 __user *) 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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,214 @@
|
|||
/* savage_drm.h -- Public header for the savage driver
|
||||
*
|
||||
* Copyright 2004 Felix Kuehling
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license,
|
||||
* 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/savage_drm.h,v 1.2 2005/11/28 23:13:55 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __SAVAGE_DRM_H__
|
||||
#define __SAVAGE_DRM_H__
|
||||
|
||||
#ifndef __SAVAGE_SAREA_DEFINES__
|
||||
#define __SAVAGE_SAREA_DEFINES__
|
||||
|
||||
/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
|
||||
* regions, subject to a minimum region size of (1<<16) == 64k.
|
||||
*
|
||||
* Clients may subdivide regions internally, but when sharing between
|
||||
* clients, the region size is the minimum granularity.
|
||||
*/
|
||||
|
||||
#define SAVAGE_CARD_HEAP 0
|
||||
#define SAVAGE_AGP_HEAP 1
|
||||
#define SAVAGE_NR_TEX_HEAPS 2
|
||||
#define SAVAGE_NR_TEX_REGIONS 16
|
||||
#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16
|
||||
|
||||
#endif /* __SAVAGE_SAREA_DEFINES__ */
|
||||
|
||||
typedef struct _drm_savage_sarea {
|
||||
/* LRU lists for texture memory in agp space and on the card.
|
||||
*/
|
||||
drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS+1];
|
||||
unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
|
||||
|
||||
/* Mechanism to validate card state.
|
||||
*/
|
||||
int ctxOwner;
|
||||
} drm_savage_sarea_t, *drm_savage_sarea_ptr;
|
||||
|
||||
/* Savage-specific ioctls
|
||||
*/
|
||||
#define DRM_SAVAGE_BCI_INIT 0x00
|
||||
#define DRM_SAVAGE_BCI_CMDBUF 0x01
|
||||
#define DRM_SAVAGE_BCI_EVENT_EMIT 0x02
|
||||
#define DRM_SAVAGE_BCI_EVENT_WAIT 0x03
|
||||
|
||||
#define DRM_IOCTL_SAVAGE_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
|
||||
#define DRM_IOCTL_SAVAGE_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
|
||||
#define DRM_IOCTL_SAVAGE_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
|
||||
#define DRM_IOCTL_SAVAGE_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
|
||||
|
||||
#define SAVAGE_DMA_PCI 1
|
||||
#define SAVAGE_DMA_AGP 3
|
||||
typedef struct drm_savage_init {
|
||||
enum {
|
||||
SAVAGE_INIT_BCI = 1,
|
||||
SAVAGE_CLEANUP_BCI = 2
|
||||
} func;
|
||||
unsigned int sarea_priv_offset;
|
||||
|
||||
/* some parameters */
|
||||
unsigned int cob_size;
|
||||
unsigned int bci_threshold_lo, bci_threshold_hi;
|
||||
unsigned int dma_type;
|
||||
|
||||
/* frame buffer layout */
|
||||
unsigned int fb_bpp;
|
||||
unsigned int front_offset, front_pitch;
|
||||
unsigned int back_offset, back_pitch;
|
||||
unsigned int depth_bpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
|
||||
/* local textures */
|
||||
unsigned int texture_offset;
|
||||
unsigned int texture_size;
|
||||
|
||||
/* physical locations of non-permanent maps */
|
||||
unsigned long status_offset;
|
||||
unsigned long buffers_offset;
|
||||
unsigned long agp_textures_offset;
|
||||
unsigned long cmd_dma_offset;
|
||||
} drm_savage_init_t;
|
||||
|
||||
typedef union drm_savage_cmd_header drm_savage_cmd_header_t;
|
||||
typedef struct drm_savage_cmdbuf {
|
||||
/* command buffer in client's address space */
|
||||
drm_savage_cmd_header_t __user *cmd_addr;
|
||||
unsigned int size; /* size of the command buffer in 64bit units */
|
||||
|
||||
unsigned int dma_idx; /* DMA buffer index to use */
|
||||
int discard; /* discard DMA buffer when done */
|
||||
/* vertex buffer in client's address space */
|
||||
unsigned int __user *vb_addr;
|
||||
unsigned int vb_size; /* size of client vertex buffer in bytes */
|
||||
unsigned int vb_stride; /* stride of vertices in 32bit words */
|
||||
/* boxes in client's address space */
|
||||
drm_clip_rect_t __user *box_addr;
|
||||
unsigned int nbox; /* number of clipping boxes */
|
||||
} drm_savage_cmdbuf_t;
|
||||
|
||||
#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */
|
||||
#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */
|
||||
#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */
|
||||
typedef struct drm_savage_event {
|
||||
unsigned int count;
|
||||
unsigned int flags;
|
||||
} drm_savage_event_emit_t, drm_savage_event_wait_t;
|
||||
|
||||
/* Commands for the cmdbuf ioctl
|
||||
*/
|
||||
#define SAVAGE_CMD_STATE 0 /* a range of state registers */
|
||||
#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */
|
||||
#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */
|
||||
#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */
|
||||
#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */
|
||||
#define SAVAGE_CMD_CLEAR 5 /* clear buffers */
|
||||
#define SAVAGE_CMD_SWAP 6 /* swap buffers */
|
||||
|
||||
/* Primitive types
|
||||
*/
|
||||
#define SAVAGE_PRIM_TRILIST 0 /* triangle list */
|
||||
#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */
|
||||
#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */
|
||||
#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat
|
||||
* shading on s3d */
|
||||
|
||||
/* Skip flags (vertex format)
|
||||
*/
|
||||
#define SAVAGE_SKIP_Z 0x01
|
||||
#define SAVAGE_SKIP_W 0x02
|
||||
#define SAVAGE_SKIP_C0 0x04
|
||||
#define SAVAGE_SKIP_C1 0x08
|
||||
#define SAVAGE_SKIP_S0 0x10
|
||||
#define SAVAGE_SKIP_T0 0x20
|
||||
#define SAVAGE_SKIP_ST0 0x30
|
||||
#define SAVAGE_SKIP_S1 0x40
|
||||
#define SAVAGE_SKIP_T1 0x80
|
||||
#define SAVAGE_SKIP_ST1 0xc0
|
||||
#define SAVAGE_SKIP_ALL_S3D 0x3f
|
||||
#define SAVAGE_SKIP_ALL_S4 0xff
|
||||
|
||||
/* Buffer names for clear command
|
||||
*/
|
||||
#define SAVAGE_FRONT 0x1
|
||||
#define SAVAGE_BACK 0x2
|
||||
#define SAVAGE_DEPTH 0x4
|
||||
|
||||
/* 64-bit command header
|
||||
*/
|
||||
union drm_savage_cmd_header {
|
||||
struct {
|
||||
unsigned char cmd; /* command */
|
||||
unsigned char pad0;
|
||||
unsigned short pad1;
|
||||
unsigned short pad2;
|
||||
unsigned short pad3;
|
||||
} cmd; /* generic */
|
||||
struct {
|
||||
unsigned char cmd;
|
||||
unsigned char global; /* need idle engine? */
|
||||
unsigned short count; /* number of consecutive registers */
|
||||
unsigned short start; /* first register */
|
||||
unsigned short pad3;
|
||||
} state; /* SAVAGE_CMD_STATE */
|
||||
struct {
|
||||
unsigned char cmd;
|
||||
unsigned char prim; /* primitive type */
|
||||
unsigned short skip; /* vertex format (skip flags) */
|
||||
unsigned short count; /* number of vertices */
|
||||
unsigned short start; /* first vertex in DMA/vertex buffer */
|
||||
} prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */
|
||||
struct {
|
||||
unsigned char cmd;
|
||||
unsigned char prim;
|
||||
unsigned short skip;
|
||||
unsigned short count; /* number of indices that follow */
|
||||
unsigned short pad3;
|
||||
} idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */
|
||||
struct {
|
||||
unsigned char cmd;
|
||||
unsigned char pad0;
|
||||
unsigned short pad1;
|
||||
unsigned int flags;
|
||||
} clear0; /* SAVAGE_CMD_CLEAR */
|
||||
struct {
|
||||
unsigned int mask;
|
||||
unsigned int value;
|
||||
} clear1; /* SAVAGE_CMD_CLEAR data */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,133 @@
|
|||
/* savage_drv.c -- Savage DRI driver
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2005 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* ERIC ANHOLT 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:
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/savage_drv.c,v 1.3 2005/12/20 22:44:36 jhb Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "savage_drm.h"
|
||||
#include "savage_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t savage_pciidlist[] = {
|
||||
savage_PCI_IDS
|
||||
};
|
||||
|
||||
static void savage_configure(drm_device_t *dev)
|
||||
{
|
||||
dev->driver.buf_priv_size = sizeof(drm_savage_buf_priv_t);
|
||||
dev->driver.load = savage_driver_load;
|
||||
dev->driver.firstopen = savage_driver_firstopen;
|
||||
dev->driver.lastclose = savage_driver_lastclose;
|
||||
dev->driver.unload = savage_driver_unload;
|
||||
dev->driver.reclaim_buffers_locked = savage_reclaim_buffers;
|
||||
dev->driver.dma_ioctl = savage_bci_buffers;
|
||||
|
||||
dev->driver.ioctls = savage_ioctls;
|
||||
dev->driver.max_ioctl = savage_max_ioctl;
|
||||
|
||||
dev->driver.name = DRIVER_NAME;
|
||||
dev->driver.desc = DRIVER_DESC;
|
||||
dev->driver.date = DRIVER_DATE;
|
||||
dev->driver.major = DRIVER_MAJOR;
|
||||
dev->driver.minor = DRIVER_MINOR;
|
||||
dev->driver.patchlevel = DRIVER_PATCHLEVEL;
|
||||
|
||||
dev->driver.use_agp = 1;
|
||||
dev->driver.use_mtrr = 1;
|
||||
dev->driver.use_pci_dma = 1;
|
||||
dev->driver.use_dma = 1;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
savage_probe(device_t dev)
|
||||
{
|
||||
return drm_probe(dev, savage_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
savage_attach(device_t nbdev)
|
||||
{
|
||||
drm_device_t *dev = device_get_softc(nbdev);
|
||||
|
||||
bzero(dev, sizeof(drm_device_t));
|
||||
savage_configure(dev);
|
||||
return drm_attach(nbdev, savage_pciidlist);
|
||||
}
|
||||
|
||||
static device_method_t savage_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, savage_probe),
|
||||
DEVMETHOD(device_attach, savage_attach),
|
||||
DEVMETHOD(device_detach, drm_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t savage_driver = {
|
||||
"drm",
|
||||
savage_methods,
|
||||
sizeof(drm_device_t)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(savage, vgapci, savage_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(savage, pci, savage_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(savage, drm, 1, 1, 1);
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
static int
|
||||
savagedrm_probe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
return drm_probe(pa, savage_pciidlist);
|
||||
}
|
||||
|
||||
static void
|
||||
savagedrm_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
drm_device_t *dev = (drm_device_t *)self;
|
||||
|
||||
savage_configure(dev);
|
||||
return drm_attach(self, pa, savage_pciidlist);
|
||||
}
|
||||
|
||||
CFATTACH_DECL(savagedrm, sizeof(drm_device_t), savagedrm_probe, savagedrm_attach,
|
||||
drm_detach, drm_activate);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,580 @@
|
|||
/* savage_drv.h -- Private header for the savage driver */
|
||||
/*-
|
||||
* Copyright 2004 Felix Kuehling
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license,
|
||||
* 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/savage_drv.h,v 1.2 2005/11/28 23:13:55 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __SAVAGE_DRV_H__
|
||||
#define __SAVAGE_DRV_H__
|
||||
|
||||
#define DRIVER_AUTHOR "Felix Kuehling"
|
||||
|
||||
#define DRIVER_NAME "savage"
|
||||
#define DRIVER_DESC "Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]"
|
||||
#define DRIVER_DATE "20050313"
|
||||
|
||||
#define DRIVER_MAJOR 2
|
||||
#define DRIVER_MINOR 4
|
||||
#define DRIVER_PATCHLEVEL 1
|
||||
/* Interface history:
|
||||
*
|
||||
* 1.x The DRM driver from the VIA/S3 code drop, basically a dummy
|
||||
* 2.0 The first real DRM
|
||||
* 2.1 Scissors registers managed by the DRM, 3D operations clipped by
|
||||
* cliprects of the cmdbuf ioctl
|
||||
* 2.2 Implemented SAVAGE_CMD_DMA_IDX and SAVAGE_CMD_VB_IDX
|
||||
* 2.3 Event counters used by BCI_EVENT_EMIT/WAIT ioctls are now 32 bits
|
||||
* wide and thus very long lived (unlikely to ever wrap). The size
|
||||
* in the struct was 32 bits before, but only 16 bits were used
|
||||
* 2.4 Implemented command DMA. Now drm_savage_init_t.cmd_dma_offset is
|
||||
* actually used
|
||||
*/
|
||||
|
||||
typedef struct drm_savage_age {
|
||||
uint16_t event;
|
||||
unsigned int wrap;
|
||||
} drm_savage_age_t;
|
||||
|
||||
typedef struct drm_savage_buf_priv {
|
||||
struct drm_savage_buf_priv *next;
|
||||
struct drm_savage_buf_priv *prev;
|
||||
drm_savage_age_t age;
|
||||
drm_buf_t *buf;
|
||||
} drm_savage_buf_priv_t;
|
||||
|
||||
typedef struct drm_savage_dma_page {
|
||||
drm_savage_age_t age;
|
||||
unsigned int used, flushed;
|
||||
} drm_savage_dma_page_t;
|
||||
#define SAVAGE_DMA_PAGE_SIZE 1024 /* in dwords */
|
||||
/* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command
|
||||
* size of 16kbytes or 4k entries. Minimum requirement would be
|
||||
* 10kbytes for 255 40-byte vertices in one drawing command. */
|
||||
#define SAVAGE_FAKE_DMA_SIZE (SAVAGE_DMA_PAGE_SIZE*4*4)
|
||||
|
||||
/* interesting bits of hardware state that are saved in dev_priv */
|
||||
typedef union {
|
||||
struct drm_savage_common_state {
|
||||
uint32_t vbaddr;
|
||||
} common;
|
||||
struct {
|
||||
unsigned char pad[sizeof(struct drm_savage_common_state)];
|
||||
uint32_t texctrl, texaddr;
|
||||
uint32_t scstart, new_scstart;
|
||||
uint32_t scend, new_scend;
|
||||
} s3d;
|
||||
struct {
|
||||
unsigned char pad[sizeof(struct drm_savage_common_state)];
|
||||
uint32_t texdescr, texaddr0, texaddr1;
|
||||
uint32_t drawctrl0, new_drawctrl0;
|
||||
uint32_t drawctrl1, new_drawctrl1;
|
||||
} s4;
|
||||
} drm_savage_state_t;
|
||||
|
||||
/* these chip tags should match the ones in the 2D driver in savage_regs.h. */
|
||||
enum savage_family {
|
||||
S3_UNKNOWN = 0,
|
||||
S3_SAVAGE3D,
|
||||
S3_SAVAGE_MX,
|
||||
S3_SAVAGE4,
|
||||
S3_PROSAVAGE,
|
||||
S3_TWISTER,
|
||||
S3_PROSAVAGEDDR,
|
||||
S3_SUPERSAVAGE,
|
||||
S3_SAVAGE2000,
|
||||
S3_LAST
|
||||
};
|
||||
|
||||
extern drm_ioctl_desc_t savage_ioctls[];
|
||||
extern int savage_max_ioctl;
|
||||
|
||||
#define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
|
||||
|
||||
#define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) \
|
||||
|| (chip==S3_PROSAVAGE) \
|
||||
|| (chip==S3_TWISTER) \
|
||||
|| (chip==S3_PROSAVAGEDDR))
|
||||
|
||||
#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
|
||||
|
||||
#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
|
||||
|
||||
#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) \
|
||||
||(chip==S3_PROSAVAGEDDR))
|
||||
|
||||
/* flags */
|
||||
#define SAVAGE_IS_AGP 1
|
||||
|
||||
typedef struct drm_savage_private {
|
||||
drm_savage_sarea_t *sarea_priv;
|
||||
|
||||
drm_savage_buf_priv_t head, tail;
|
||||
|
||||
/* who am I? */
|
||||
enum savage_family chipset;
|
||||
|
||||
unsigned int cob_size;
|
||||
unsigned int bci_threshold_lo, bci_threshold_hi;
|
||||
unsigned int dma_type;
|
||||
|
||||
/* frame buffer layout */
|
||||
unsigned int fb_bpp;
|
||||
unsigned int front_offset, front_pitch;
|
||||
unsigned int back_offset, back_pitch;
|
||||
unsigned int depth_bpp;
|
||||
unsigned int depth_offset, depth_pitch;
|
||||
|
||||
/* bitmap descriptors for swap and clear */
|
||||
unsigned int front_bd, back_bd, depth_bd;
|
||||
|
||||
/* local textures */
|
||||
unsigned int texture_offset;
|
||||
unsigned int texture_size;
|
||||
|
||||
/* memory regions in physical memory */
|
||||
drm_local_map_t *sarea;
|
||||
drm_local_map_t *mmio;
|
||||
drm_local_map_t *fb;
|
||||
drm_local_map_t *aperture;
|
||||
drm_local_map_t *status;
|
||||
drm_local_map_t *agp_textures;
|
||||
drm_local_map_t *cmd_dma;
|
||||
drm_local_map_t fake_dma;
|
||||
|
||||
struct {
|
||||
int handle;
|
||||
unsigned long base, size;
|
||||
} mtrr[3];
|
||||
|
||||
/* BCI and status-related stuff */
|
||||
volatile uint32_t *status_ptr, *bci_ptr;
|
||||
uint32_t status_used_mask;
|
||||
uint16_t event_counter;
|
||||
unsigned int event_wrap;
|
||||
|
||||
/* Savage4 command DMA */
|
||||
drm_savage_dma_page_t *dma_pages;
|
||||
unsigned int nr_dma_pages, first_dma_page, current_dma_page;
|
||||
drm_savage_age_t last_dma_age;
|
||||
|
||||
/* saved hw state for global/local check on S3D */
|
||||
uint32_t hw_draw_ctrl, hw_zbuf_ctrl;
|
||||
/* and for scissors (global, so don't emit if not changed) */
|
||||
uint32_t hw_scissors_start, hw_scissors_end;
|
||||
|
||||
drm_savage_state_t state;
|
||||
|
||||
/* after emitting a wait cmd Savage3D needs 63 nops before next DMA */
|
||||
unsigned int waiting;
|
||||
|
||||
/* config/hardware-dependent function pointers */
|
||||
int (*wait_fifo)(struct drm_savage_private *dev_priv, unsigned int n);
|
||||
int (*wait_evnt)(struct drm_savage_private *dev_priv, uint16_t e);
|
||||
/* Err, there is a macro wait_event in include/linux/wait.h.
|
||||
* Avoid unwanted macro expansion. */
|
||||
void (*emit_clip_rect)(struct drm_savage_private *dev_priv,
|
||||
const drm_clip_rect_t *pbox);
|
||||
void (*dma_flush)(struct drm_savage_private *dev_priv);
|
||||
} drm_savage_private_t;
|
||||
|
||||
/* ioctls */
|
||||
extern int savage_bci_cmdbuf(DRM_IOCTL_ARGS);
|
||||
extern int savage_bci_buffers(DRM_IOCTL_ARGS);
|
||||
|
||||
/* BCI functions */
|
||||
extern uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
|
||||
unsigned int flags);
|
||||
extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf);
|
||||
extern void savage_dma_reset(drm_savage_private_t *dev_priv);
|
||||
extern void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page);
|
||||
extern uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv,
|
||||
unsigned int n);
|
||||
extern int savage_driver_load(drm_device_t *dev, unsigned long chipset);
|
||||
extern int savage_driver_firstopen(drm_device_t *dev);
|
||||
extern void savage_driver_lastclose(drm_device_t *dev);
|
||||
extern int savage_driver_unload(drm_device_t *dev);
|
||||
extern int savage_do_cleanup_bci(drm_device_t *dev);
|
||||
extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
|
||||
|
||||
/* state functions */
|
||||
extern void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
|
||||
const drm_clip_rect_t *pbox);
|
||||
extern void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
|
||||
const drm_clip_rect_t *pbox);
|
||||
|
||||
#define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */
|
||||
#define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */
|
||||
#define SAVAGE_MMIO_SIZE 0x00080000 /* 512kB */
|
||||
#define SAVAGE_APERTURE_OFFSET 0x02000000 /* 32MB */
|
||||
#define SAVAGE_APERTURE_SIZE 0x05000000 /* 5 tiled surfaces, 16MB each */
|
||||
|
||||
#define SAVAGE_BCI_OFFSET 0x00010000 /* offset of the BCI region
|
||||
* inside the MMIO region */
|
||||
#define SAVAGE_BCI_FIFO_SIZE 32 /* number of entries in on-chip
|
||||
* BCI FIFO */
|
||||
|
||||
/*
|
||||
* MMIO registers
|
||||
*/
|
||||
#define SAVAGE_STATUS_WORD0 0x48C00
|
||||
#define SAVAGE_STATUS_WORD1 0x48C04
|
||||
#define SAVAGE_ALT_STATUS_WORD0 0x48C60
|
||||
|
||||
#define SAVAGE_FIFO_USED_MASK_S3D 0x0001ffff
|
||||
#define SAVAGE_FIFO_USED_MASK_S4 0x001fffff
|
||||
|
||||
/* Copied from savage_bci.h in the 2D driver with some renaming. */
|
||||
|
||||
/* Bitmap descriptors */
|
||||
#define SAVAGE_BD_STRIDE_SHIFT 0
|
||||
#define SAVAGE_BD_BPP_SHIFT 16
|
||||
#define SAVAGE_BD_TILE_SHIFT 24
|
||||
#define SAVAGE_BD_BW_DISABLE (1<<28)
|
||||
/* common: */
|
||||
#define SAVAGE_BD_TILE_LINEAR 0
|
||||
/* savage4, MX, IX, 3D */
|
||||
#define SAVAGE_BD_TILE_16BPP 2
|
||||
#define SAVAGE_BD_TILE_32BPP 3
|
||||
/* twister, prosavage, DDR, supersavage, 2000 */
|
||||
#define SAVAGE_BD_TILE_DEST 1
|
||||
#define SAVAGE_BD_TILE_TEXTURE 2
|
||||
/* GBD - BCI enable */
|
||||
/* savage4, MX, IX, 3D */
|
||||
#define SAVAGE_GBD_BCI_ENABLE 8
|
||||
/* twister, prosavage, DDR, supersavage, 2000 */
|
||||
#define SAVAGE_GBD_BCI_ENABLE_TWISTER 0
|
||||
|
||||
#define SAVAGE_GBD_BIG_ENDIAN 4
|
||||
#define SAVAGE_GBD_LITTLE_ENDIAN 0
|
||||
#define SAVAGE_GBD_64 1
|
||||
|
||||
/* Global Bitmap Descriptor */
|
||||
#define SAVAGE_BCI_GLB_BD_LOW 0x8168
|
||||
#define SAVAGE_BCI_GLB_BD_HIGH 0x816C
|
||||
|
||||
/*
|
||||
* BCI registers
|
||||
*/
|
||||
/* Savage4/Twister/ProSavage 3D registers */
|
||||
#define SAVAGE_DRAWLOCALCTRL_S4 0x1e
|
||||
#define SAVAGE_TEXPALADDR_S4 0x1f
|
||||
#define SAVAGE_TEXCTRL0_S4 0x20
|
||||
#define SAVAGE_TEXCTRL1_S4 0x21
|
||||
#define SAVAGE_TEXADDR0_S4 0x22
|
||||
#define SAVAGE_TEXADDR1_S4 0x23
|
||||
#define SAVAGE_TEXBLEND0_S4 0x24
|
||||
#define SAVAGE_TEXBLEND1_S4 0x25
|
||||
#define SAVAGE_TEXXPRCLR_S4 0x26 /* never used */
|
||||
#define SAVAGE_TEXDESCR_S4 0x27
|
||||
#define SAVAGE_FOGTABLE_S4 0x28
|
||||
#define SAVAGE_FOGCTRL_S4 0x30
|
||||
#define SAVAGE_STENCILCTRL_S4 0x31
|
||||
#define SAVAGE_ZBUFCTRL_S4 0x32
|
||||
#define SAVAGE_ZBUFOFF_S4 0x33
|
||||
#define SAVAGE_DESTCTRL_S4 0x34
|
||||
#define SAVAGE_DRAWCTRL0_S4 0x35
|
||||
#define SAVAGE_DRAWCTRL1_S4 0x36
|
||||
#define SAVAGE_ZWATERMARK_S4 0x37
|
||||
#define SAVAGE_DESTTEXRWWATERMARK_S4 0x38
|
||||
#define SAVAGE_TEXBLENDCOLOR_S4 0x39
|
||||
/* Savage3D/MX/IX 3D registers */
|
||||
#define SAVAGE_TEXPALADDR_S3D 0x18
|
||||
#define SAVAGE_TEXXPRCLR_S3D 0x19 /* never used */
|
||||
#define SAVAGE_TEXADDR_S3D 0x1A
|
||||
#define SAVAGE_TEXDESCR_S3D 0x1B
|
||||
#define SAVAGE_TEXCTRL_S3D 0x1C
|
||||
#define SAVAGE_FOGTABLE_S3D 0x20
|
||||
#define SAVAGE_FOGCTRL_S3D 0x30
|
||||
#define SAVAGE_DRAWCTRL_S3D 0x31
|
||||
#define SAVAGE_ZBUFCTRL_S3D 0x32
|
||||
#define SAVAGE_ZBUFOFF_S3D 0x33
|
||||
#define SAVAGE_DESTCTRL_S3D 0x34
|
||||
#define SAVAGE_SCSTART_S3D 0x35
|
||||
#define SAVAGE_SCEND_S3D 0x36
|
||||
#define SAVAGE_ZWATERMARK_S3D 0x37
|
||||
#define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38
|
||||
/* common stuff */
|
||||
#define SAVAGE_VERTBUFADDR 0x3e
|
||||
#define SAVAGE_BITPLANEWTMASK 0xd7
|
||||
#define SAVAGE_DMABUFADDR 0x51
|
||||
|
||||
/* texture enable bits (needed for tex addr checking) */
|
||||
#define SAVAGE_TEXCTRL_TEXEN_MASK 0x00010000 /* S3D */
|
||||
#define SAVAGE_TEXDESCR_TEX0EN_MASK 0x02000000 /* S4 */
|
||||
#define SAVAGE_TEXDESCR_TEX1EN_MASK 0x04000000 /* S4 */
|
||||
|
||||
/* Global fields in Savage4/Twister/ProSavage 3D registers:
|
||||
*
|
||||
* All texture registers and DrawLocalCtrl are local. All other
|
||||
* registers are global. */
|
||||
|
||||
/* Global fields in Savage3D/MX/IX 3D registers:
|
||||
*
|
||||
* All texture registers are local. DrawCtrl and ZBufCtrl are
|
||||
* partially local. All other registers are global.
|
||||
*
|
||||
* DrawCtrl global fields: cullMode, alphaTestCmpFunc, alphaTestEn, alphaRefVal
|
||||
* ZBufCtrl global fields: zCmpFunc, zBufEn
|
||||
*/
|
||||
#define SAVAGE_DRAWCTRL_S3D_GLOBAL 0x03f3c00c
|
||||
#define SAVAGE_ZBUFCTRL_S3D_GLOBAL 0x00000027
|
||||
|
||||
/* Masks for scissor bits (drawCtrl[01] on s4, scissorStart/End on s3d)
|
||||
*/
|
||||
#define SAVAGE_SCISSOR_MASK_S4 0x00fff7ff
|
||||
#define SAVAGE_SCISSOR_MASK_S3D 0x07ff07ff
|
||||
|
||||
/*
|
||||
* BCI commands
|
||||
*/
|
||||
#define BCI_CMD_NOP 0x40000000
|
||||
#define BCI_CMD_RECT 0x48000000
|
||||
#define BCI_CMD_RECT_XP 0x01000000
|
||||
#define BCI_CMD_RECT_YP 0x02000000
|
||||
#define BCI_CMD_SCANLINE 0x50000000
|
||||
#define BCI_CMD_LINE 0x5C000000
|
||||
#define BCI_CMD_LINE_LAST_PIXEL 0x58000000
|
||||
#define BCI_CMD_BYTE_TEXT 0x63000000
|
||||
#define BCI_CMD_NT_BYTE_TEXT 0x67000000
|
||||
#define BCI_CMD_BIT_TEXT 0x6C000000
|
||||
#define BCI_CMD_GET_ROP(cmd) (((cmd) >> 16) & 0xFF)
|
||||
#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16))
|
||||
#define BCI_CMD_SEND_COLOR 0x00008000
|
||||
|
||||
#define BCI_CMD_CLIP_NONE 0x00000000
|
||||
#define BCI_CMD_CLIP_CURRENT 0x00002000
|
||||
#define BCI_CMD_CLIP_LR 0x00004000
|
||||
#define BCI_CMD_CLIP_NEW 0x00006000
|
||||
|
||||
#define BCI_CMD_DEST_GBD 0x00000000
|
||||
#define BCI_CMD_DEST_PBD 0x00000800
|
||||
#define BCI_CMD_DEST_PBD_NEW 0x00000C00
|
||||
#define BCI_CMD_DEST_SBD 0x00001000
|
||||
#define BCI_CMD_DEST_SBD_NEW 0x00001400
|
||||
|
||||
#define BCI_CMD_SRC_TRANSPARENT 0x00000200
|
||||
#define BCI_CMD_SRC_SOLID 0x00000000
|
||||
#define BCI_CMD_SRC_GBD 0x00000020
|
||||
#define BCI_CMD_SRC_COLOR 0x00000040
|
||||
#define BCI_CMD_SRC_MONO 0x00000060
|
||||
#define BCI_CMD_SRC_PBD_COLOR 0x00000080
|
||||
#define BCI_CMD_SRC_PBD_MONO 0x000000A0
|
||||
#define BCI_CMD_SRC_PBD_COLOR_NEW 0x000000C0
|
||||
#define BCI_CMD_SRC_PBD_MONO_NEW 0x000000E0
|
||||
#define BCI_CMD_SRC_SBD_COLOR 0x00000100
|
||||
#define BCI_CMD_SRC_SBD_MONO 0x00000120
|
||||
#define BCI_CMD_SRC_SBD_COLOR_NEW 0x00000140
|
||||
#define BCI_CMD_SRC_SBD_MONO_NEW 0x00000160
|
||||
|
||||
#define BCI_CMD_PAT_TRANSPARENT 0x00000010
|
||||
#define BCI_CMD_PAT_NONE 0x00000000
|
||||
#define BCI_CMD_PAT_COLOR 0x00000002
|
||||
#define BCI_CMD_PAT_MONO 0x00000003
|
||||
#define BCI_CMD_PAT_PBD_COLOR 0x00000004
|
||||
#define BCI_CMD_PAT_PBD_MONO 0x00000005
|
||||
#define BCI_CMD_PAT_PBD_COLOR_NEW 0x00000006
|
||||
#define BCI_CMD_PAT_PBD_MONO_NEW 0x00000007
|
||||
#define BCI_CMD_PAT_SBD_COLOR 0x00000008
|
||||
#define BCI_CMD_PAT_SBD_MONO 0x00000009
|
||||
#define BCI_CMD_PAT_SBD_COLOR_NEW 0x0000000A
|
||||
#define BCI_CMD_PAT_SBD_MONO_NEW 0x0000000B
|
||||
|
||||
#define BCI_BD_BW_DISABLE 0x10000000
|
||||
#define BCI_BD_TILE_MASK 0x03000000
|
||||
#define BCI_BD_TILE_NONE 0x00000000
|
||||
#define BCI_BD_TILE_16 0x02000000
|
||||
#define BCI_BD_TILE_32 0x03000000
|
||||
#define BCI_BD_GET_BPP(bd) (((bd) >> 16) & 0xFF)
|
||||
#define BCI_BD_SET_BPP(bd, bpp) ((bd) |= (((bpp) & 0xFF) << 16))
|
||||
#define BCI_BD_GET_STRIDE(bd) ((bd) & 0xFFFF)
|
||||
#define BCI_BD_SET_STRIDE(bd, st) ((bd) |= ((st) & 0xFFFF))
|
||||
|
||||
#define BCI_CMD_SET_REGISTER 0x96000000
|
||||
|
||||
#define BCI_CMD_WAIT 0xC0000000
|
||||
#define BCI_CMD_WAIT_3D 0x00010000
|
||||
#define BCI_CMD_WAIT_2D 0x00020000
|
||||
|
||||
#define BCI_CMD_UPDATE_EVENT_TAG 0x98000000
|
||||
|
||||
#define BCI_CMD_DRAW_PRIM 0x80000000
|
||||
#define BCI_CMD_DRAW_INDEXED_PRIM 0x88000000
|
||||
#define BCI_CMD_DRAW_CONT 0x01000000
|
||||
#define BCI_CMD_DRAW_TRILIST 0x00000000
|
||||
#define BCI_CMD_DRAW_TRISTRIP 0x02000000
|
||||
#define BCI_CMD_DRAW_TRIFAN 0x04000000
|
||||
#define BCI_CMD_DRAW_SKIPFLAGS 0x000000ff
|
||||
#define BCI_CMD_DRAW_NO_Z 0x00000001
|
||||
#define BCI_CMD_DRAW_NO_W 0x00000002
|
||||
#define BCI_CMD_DRAW_NO_CD 0x00000004
|
||||
#define BCI_CMD_DRAW_NO_CS 0x00000008
|
||||
#define BCI_CMD_DRAW_NO_U0 0x00000010
|
||||
#define BCI_CMD_DRAW_NO_V0 0x00000020
|
||||
#define BCI_CMD_DRAW_NO_UV0 0x00000030
|
||||
#define BCI_CMD_DRAW_NO_U1 0x00000040
|
||||
#define BCI_CMD_DRAW_NO_V1 0x00000080
|
||||
#define BCI_CMD_DRAW_NO_UV1 0x000000c0
|
||||
|
||||
#define BCI_CMD_DMA 0xa8000000
|
||||
|
||||
#define BCI_W_H(w, h) ((((h) << 16) | (w)) & 0x0FFF0FFF)
|
||||
#define BCI_X_Y(x, y) ((((y) << 16) | (x)) & 0x0FFF0FFF)
|
||||
#define BCI_X_W(x, y) ((((w) << 16) | (x)) & 0x0FFF0FFF)
|
||||
#define BCI_CLIP_LR(l, r) ((((r) << 16) | (l)) & 0x0FFF0FFF)
|
||||
#define BCI_CLIP_TL(t, l) ((((t) << 16) | (l)) & 0x0FFF0FFF)
|
||||
#define BCI_CLIP_BR(b, r) ((((b) << 16) | (r)) & 0x0FFF0FFF)
|
||||
|
||||
#define BCI_LINE_X_Y(x, y) (((y) << 16) | ((x) & 0xFFFF))
|
||||
#define BCI_LINE_STEPS(diag, axi) (((axi) << 16) | ((diag) & 0xFFFF))
|
||||
#define BCI_LINE_MISC(maj, ym, xp, yp, err) \
|
||||
(((maj) & 0x1FFF) | \
|
||||
((ym) ? 1<<13 : 0) | \
|
||||
((xp) ? 1<<14 : 0) | \
|
||||
((yp) ? 1<<15 : 0) | \
|
||||
((err) << 16))
|
||||
|
||||
/*
|
||||
* common commands
|
||||
*/
|
||||
#define BCI_SET_REGISTERS( first, n ) \
|
||||
BCI_WRITE(BCI_CMD_SET_REGISTER | \
|
||||
((uint32_t)(n) & 0xff) << 16 | \
|
||||
((uint32_t)(first) & 0xffff))
|
||||
#define DMA_SET_REGISTERS( first, n ) \
|
||||
DMA_WRITE(BCI_CMD_SET_REGISTER | \
|
||||
((uint32_t)(n) & 0xff) << 16 | \
|
||||
((uint32_t)(first) & 0xffff))
|
||||
|
||||
#define BCI_DRAW_PRIMITIVE(n, type, skip) \
|
||||
BCI_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
|
||||
((n) << 16))
|
||||
#define DMA_DRAW_PRIMITIVE(n, type, skip) \
|
||||
DMA_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
|
||||
((n) << 16))
|
||||
|
||||
#define BCI_DRAW_INDICES_S3D(n, type, i0) \
|
||||
BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \
|
||||
((n) << 16) | (i0))
|
||||
|
||||
#define BCI_DRAW_INDICES_S4(n, type, skip) \
|
||||
BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \
|
||||
(skip) | ((n) << 16))
|
||||
|
||||
#define BCI_DMA(n) \
|
||||
BCI_WRITE(BCI_CMD_DMA | (((n) >> 1) - 1))
|
||||
|
||||
/*
|
||||
* access to MMIO
|
||||
*/
|
||||
#define SAVAGE_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
|
||||
#define SAVAGE_WRITE(reg) DRM_WRITE32( dev_priv->mmio, (reg) )
|
||||
|
||||
/*
|
||||
* access to the burst command interface (BCI)
|
||||
*/
|
||||
#define SAVAGE_BCI_DEBUG 1
|
||||
|
||||
#define BCI_LOCALS volatile uint32_t *bci_ptr;
|
||||
|
||||
#define BEGIN_BCI( n ) do { \
|
||||
dev_priv->wait_fifo(dev_priv, (n)); \
|
||||
bci_ptr = dev_priv->bci_ptr; \
|
||||
} while(0)
|
||||
|
||||
#define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val)
|
||||
|
||||
/*
|
||||
* command DMA support
|
||||
*/
|
||||
#define SAVAGE_DMA_DEBUG 1
|
||||
|
||||
#define DMA_LOCALS uint32_t *dma_ptr;
|
||||
|
||||
#define BEGIN_DMA( n ) do { \
|
||||
unsigned int cur = dev_priv->current_dma_page; \
|
||||
unsigned int rest = SAVAGE_DMA_PAGE_SIZE - \
|
||||
dev_priv->dma_pages[cur].used; \
|
||||
if ((n) > rest) { \
|
||||
dma_ptr = savage_dma_alloc(dev_priv, (n)); \
|
||||
} else { /* fast path for small allocations */ \
|
||||
dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle + \
|
||||
cur * SAVAGE_DMA_PAGE_SIZE + \
|
||||
dev_priv->dma_pages[cur].used; \
|
||||
if (dev_priv->dma_pages[cur].used == 0) \
|
||||
savage_dma_wait(dev_priv, cur); \
|
||||
dev_priv->dma_pages[cur].used += (n); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val)
|
||||
|
||||
#define DMA_COPY(src, n) do { \
|
||||
memcpy(dma_ptr, (src), (n)*4); \
|
||||
dma_ptr += n; \
|
||||
} while(0)
|
||||
|
||||
#if SAVAGE_DMA_DEBUG
|
||||
#define DMA_COMMIT() do { \
|
||||
unsigned int cur = dev_priv->current_dma_page; \
|
||||
uint32_t *expected = (uint32_t *)dev_priv->cmd_dma->handle + \
|
||||
cur * SAVAGE_DMA_PAGE_SIZE + \
|
||||
dev_priv->dma_pages[cur].used; \
|
||||
if (dma_ptr != expected) { \
|
||||
DRM_ERROR("DMA allocation and use don't match: " \
|
||||
"%p != %p\n", expected, dma_ptr); \
|
||||
savage_dma_reset(dev_priv); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define DMA_COMMIT() do {/* nothing */} while(0)
|
||||
#endif
|
||||
|
||||
#define DMA_FLUSH() dev_priv->dma_flush(dev_priv)
|
||||
|
||||
/* Buffer aging via event tag
|
||||
*/
|
||||
|
||||
#define UPDATE_EVENT_COUNTER( ) do { \
|
||||
if (dev_priv->status_ptr) { \
|
||||
uint16_t count; \
|
||||
/* coordinate with Xserver */ \
|
||||
count = dev_priv->status_ptr[1023]; \
|
||||
if (count < dev_priv->event_counter) \
|
||||
dev_priv->event_wrap++; \
|
||||
dev_priv->event_counter = count; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define SET_AGE( age, e, w ) do { \
|
||||
(age)->event = e; \
|
||||
(age)->wrap = w; \
|
||||
} while(0)
|
||||
|
||||
#define TEST_AGE( age, e, w ) \
|
||||
( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) )
|
||||
|
||||
#endif /* __SAVAGE_DRV_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,72 @@
|
|||
/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
|
||||
/*-
|
||||
* Copyright 2005 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/sis_drm.h,v 1.6 2005/11/28 23:13:55 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __SIS_DRM_H__
|
||||
#define __SIS_DRM_H__
|
||||
|
||||
/* SiS specific ioctls */
|
||||
#define NOT_USED_0_3
|
||||
#define DRM_SIS_FB_ALLOC 0x04
|
||||
#define DRM_SIS_FB_FREE 0x05
|
||||
#define NOT_USED_6_12
|
||||
#define DRM_SIS_AGP_INIT 0x13
|
||||
#define DRM_SIS_AGP_ALLOC 0x14
|
||||
#define DRM_SIS_AGP_FREE 0x15
|
||||
#define DRM_SIS_FB_INIT 0x16
|
||||
|
||||
#define DRM_IOCTL_SIS_FB_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_FB_ALLOC, drm_sis_mem_t)
|
||||
#define DRM_IOCTL_SIS_FB_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_FREE, drm_sis_mem_t)
|
||||
#define DRM_IOCTL_SIS_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_INIT, drm_sis_agp_t)
|
||||
#define DRM_IOCTL_SIS_AGP_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_ALLOC, drm_sis_mem_t)
|
||||
#define DRM_IOCTL_SIS_AGP_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_AGP_FREE, drm_sis_mem_t)
|
||||
#define DRM_IOCTL_SIS_FB_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_INIT, drm_sis_fb_t)
|
||||
/*
|
||||
#define DRM_IOCTL_SIS_FLIP DRM_IOW( 0x48, drm_sis_flip_t)
|
||||
#define DRM_IOCTL_SIS_FLIP_INIT DRM_IO( 0x49)
|
||||
#define DRM_IOCTL_SIS_FLIP_FINAL DRM_IO( 0x50)
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int context;
|
||||
unsigned int offset;
|
||||
unsigned int size;
|
||||
unsigned long free;
|
||||
} drm_sis_mem_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int offset, size;
|
||||
} drm_sis_agp_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int offset, size;
|
||||
} drm_sis_fb_t;
|
||||
|
||||
#endif /* __SIS_DRM_H__ */
|
|
@ -0,0 +1,126 @@
|
|||
/* sis.c -- sis driver -*- linux-c -*-
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/sis_drv.c,v 1.7 2005/12/20 22:44:36 jhb Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "sis_drm.h"
|
||||
#include "sis_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t sis_pciidlist[] = {
|
||||
sis_PCI_IDS
|
||||
};
|
||||
|
||||
static void sis_configure(drm_device_t *dev)
|
||||
{
|
||||
dev->driver.buf_priv_size = 1; /* No dev_priv */
|
||||
dev->driver.context_ctor = sis_init_context;
|
||||
dev->driver.context_dtor = sis_final_context;
|
||||
|
||||
dev->driver.ioctls = sis_ioctls;
|
||||
dev->driver.max_ioctl = sis_max_ioctl;
|
||||
|
||||
dev->driver.name = DRIVER_NAME;
|
||||
dev->driver.desc = DRIVER_DESC;
|
||||
dev->driver.date = DRIVER_DATE;
|
||||
dev->driver.major = DRIVER_MAJOR;
|
||||
dev->driver.minor = DRIVER_MINOR;
|
||||
dev->driver.patchlevel = DRIVER_PATCHLEVEL;
|
||||
|
||||
dev->driver.use_agp = 1;
|
||||
dev->driver.use_mtrr = 1;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
sis_probe(device_t dev)
|
||||
{
|
||||
return drm_probe(dev, sis_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
sis_attach(device_t nbdev)
|
||||
{
|
||||
drm_device_t *dev = device_get_softc(nbdev);
|
||||
|
||||
bzero(dev, sizeof(drm_device_t));
|
||||
sis_configure(dev);
|
||||
return drm_attach(nbdev, sis_pciidlist);
|
||||
}
|
||||
|
||||
static device_method_t sis_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, sis_probe),
|
||||
DEVMETHOD(device_attach, sis_attach),
|
||||
DEVMETHOD(device_detach, drm_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t sis_driver = {
|
||||
"drm",
|
||||
sis_methods,
|
||||
sizeof(drm_device_t)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(sisdrm, vgapci, sis_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(sisdrm, pci, sis_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(sisdrm, drm, 1, 1, 1);
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
static int
|
||||
sisdrm_probe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
return drm_probe(pa, sis_pciidlist);
|
||||
}
|
||||
|
||||
static void
|
||||
sisdrm_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
drm_device_t *dev = (drm_device_t *)self;
|
||||
|
||||
sis_configure(dev);
|
||||
return drm_attach(self, pa, sis_pciidlist);
|
||||
}
|
||||
|
||||
CFATTACH_DECL(sisdrm, sizeof(drm_device_t), sisdrm_probe, sisdrm_attach,
|
||||
drm_detach, drm_activate);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/sis_drv.h,v 1.4 2005/11/28 23:13:55 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef _SIS_DRV_H_
|
||||
#define _SIS_DRV_H_
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
|
||||
#define DRIVER_AUTHOR "SIS"
|
||||
#define DRIVER_NAME "sis"
|
||||
#define DRIVER_DESC "SIS 300/630/540"
|
||||
#define DRIVER_DATE "20030826"
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 1
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
#include "sis_ds.h"
|
||||
|
||||
typedef struct drm_sis_private {
|
||||
memHeap_t *AGPHeap;
|
||||
memHeap_t *FBHeap;
|
||||
} drm_sis_private_t;
|
||||
|
||||
extern int sis_init_context(drm_device_t * dev, int context);
|
||||
extern int sis_final_context(drm_device_t * dev, int context);
|
||||
|
||||
extern drm_ioctl_desc_t sis_ioctls[];
|
||||
extern int sis_max_ioctl;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,304 @@
|
|||
/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
|
||||
* Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
|
||||
*
|
||||
* Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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:
|
||||
* Sung-Ching Lin <sclin@sis.com.tw>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/sis_ds.c,v 1.5 2006/04/09 20:45:45 anholt Exp $");
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "sis_ds.h"
|
||||
|
||||
/* Set Data Structure, not check repeated value
|
||||
* temporarily used
|
||||
*/
|
||||
|
||||
set_t *setInit(void)
|
||||
{
|
||||
int i;
|
||||
set_t *set;
|
||||
|
||||
set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
|
||||
if (set != NULL) {
|
||||
for (i = 0; i < SET_SIZE; i++) {
|
||||
set->list[i].free_next = i + 1;
|
||||
set->list[i].alloc_next = -1;
|
||||
}
|
||||
set->list[SET_SIZE - 1].free_next = -1;
|
||||
set->free = 0;
|
||||
set->alloc = -1;
|
||||
set->trace = -1;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
int setAdd(set_t * set, ITEM_TYPE item)
|
||||
{
|
||||
int sfree = set->free;
|
||||
|
||||
if (sfree != -1) {
|
||||
set->list[sfree].val = item;
|
||||
set->free = set->list[sfree].free_next;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
set->list[sfree].alloc_next = set->alloc;
|
||||
set->alloc = sfree;
|
||||
set->list[sfree].free_next = -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setDel(set_t * set, ITEM_TYPE item)
|
||||
{
|
||||
int alloc = set->alloc;
|
||||
int prev = -1;
|
||||
|
||||
while (alloc != -1) {
|
||||
if (set->list[alloc].val == item) {
|
||||
if (prev != -1)
|
||||
set->list[prev].alloc_next =
|
||||
set->list[alloc].alloc_next;
|
||||
else
|
||||
set->alloc = set->list[alloc].alloc_next;
|
||||
break;
|
||||
}
|
||||
prev = alloc;
|
||||
alloc = set->list[alloc].alloc_next;
|
||||
}
|
||||
|
||||
if (alloc == -1)
|
||||
return 0;
|
||||
|
||||
set->list[alloc].free_next = set->free;
|
||||
set->free = alloc;
|
||||
set->list[alloc].alloc_next = -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* setFirst -> setAdd -> setNext is wrong */
|
||||
|
||||
int setFirst(set_t * set, ITEM_TYPE * item)
|
||||
{
|
||||
if (set->alloc == -1)
|
||||
return 0;
|
||||
|
||||
*item = set->list[set->alloc].val;
|
||||
set->trace = set->list[set->alloc].alloc_next;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setNext(set_t * set, ITEM_TYPE * item)
|
||||
{
|
||||
if (set->trace == -1)
|
||||
return 0;
|
||||
|
||||
*item = set->list[set->trace].val;
|
||||
set->trace = set->list[set->trace].alloc_next;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setDestroy(set_t * set)
|
||||
{
|
||||
drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* GLX Hardware Device Driver common code
|
||||
* Copyright (C) 1999 Wittawat Yamwong
|
||||
*
|
||||
* 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 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
|
||||
* WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define ISFREE(bptr) ((bptr)->free)
|
||||
|
||||
memHeap_t *mmInit(int ofs, int size)
|
||||
{
|
||||
PMemBlock blocks;
|
||||
|
||||
if (size <= 0)
|
||||
return NULL;
|
||||
|
||||
blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
|
||||
if (blocks != NULL) {
|
||||
blocks->ofs = ofs;
|
||||
blocks->size = size;
|
||||
blocks->free = 1;
|
||||
return (memHeap_t *) blocks;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Checks if a pointer 'b' is part of the heap 'heap' */
|
||||
int mmBlockInHeap(memHeap_t * heap, PMemBlock b)
|
||||
{
|
||||
TMemBlock *p;
|
||||
|
||||
if (heap == NULL || b == NULL)
|
||||
return 0;
|
||||
|
||||
p = heap;
|
||||
while (p != NULL && p != b) {
|
||||
p = p->next;
|
||||
}
|
||||
if (p == b)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static TMemBlock *SliceBlock(TMemBlock * p,
|
||||
int startofs, int size,
|
||||
int reserved, int alignment)
|
||||
{
|
||||
TMemBlock *newblock;
|
||||
|
||||
/* break left */
|
||||
if (startofs > p->ofs) {
|
||||
newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
|
||||
DRM_MEM_DRIVER);
|
||||
newblock->ofs = startofs;
|
||||
newblock->size = p->size - (startofs - p->ofs);
|
||||
newblock->free = 1;
|
||||
newblock->next = p->next;
|
||||
p->size -= newblock->size;
|
||||
p->next = newblock;
|
||||
p = newblock;
|
||||
}
|
||||
|
||||
/* break right */
|
||||
if (size < p->size) {
|
||||
newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
|
||||
DRM_MEM_DRIVER);
|
||||
newblock->ofs = startofs + size;
|
||||
newblock->size = p->size - size;
|
||||
newblock->free = 1;
|
||||
newblock->next = p->next;
|
||||
p->size = size;
|
||||
p->next = newblock;
|
||||
}
|
||||
|
||||
/* p = middle block */
|
||||
p->align = alignment;
|
||||
p->free = 0;
|
||||
p->reserved = reserved;
|
||||
return p;
|
||||
}
|
||||
|
||||
PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch)
|
||||
{
|
||||
int mask, startofs, endofs;
|
||||
TMemBlock *p;
|
||||
|
||||
if (heap == NULL || align2 < 0 || size <= 0)
|
||||
return NULL;
|
||||
|
||||
mask = (1 << align2) - 1;
|
||||
startofs = 0;
|
||||
p = (TMemBlock *) heap;
|
||||
while (p != NULL) {
|
||||
if (ISFREE(p)) {
|
||||
startofs = (p->ofs + mask) & ~mask;
|
||||
if (startofs < startSearch) {
|
||||
startofs = startSearch;
|
||||
}
|
||||
endofs = startofs + size;
|
||||
if (endofs <= (p->ofs + p->size))
|
||||
break;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
p = SliceBlock(p, startofs, size, 0, mask + 1);
|
||||
p->heap = heap;
|
||||
return p;
|
||||
}
|
||||
|
||||
static __inline__ int Join2Blocks(TMemBlock * p)
|
||||
{
|
||||
if (p->free && p->next && p->next->free) {
|
||||
TMemBlock *q = p->next;
|
||||
p->size += q->size;
|
||||
p->next = q->next;
|
||||
drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmFreeMem(PMemBlock b)
|
||||
{
|
||||
TMemBlock *p, *prev;
|
||||
|
||||
if (b == NULL)
|
||||
return 0;
|
||||
if (b->heap == NULL)
|
||||
return -1;
|
||||
|
||||
p = b->heap;
|
||||
prev = NULL;
|
||||
while (p != NULL && p != b) {
|
||||
prev = p;
|
||||
p = p->next;
|
||||
}
|
||||
if (p == NULL || p->free || p->reserved)
|
||||
return -1;
|
||||
|
||||
p->free = 1;
|
||||
Join2Blocks(p);
|
||||
if (prev)
|
||||
Join2Blocks(prev);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
|
||||
* Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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:
|
||||
* Sung-Ching Lin <sclin@sis.com.tw>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/sis_ds.h,v 1.6 2006/04/09 20:45:45 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __SIS_DS_H__
|
||||
#define __SIS_DS_H__
|
||||
|
||||
/* Set Data Structure */
|
||||
|
||||
#define SET_SIZE 5000
|
||||
|
||||
typedef unsigned long ITEM_TYPE;
|
||||
|
||||
typedef struct {
|
||||
ITEM_TYPE val;
|
||||
int alloc_next, free_next;
|
||||
} list_item_t;
|
||||
|
||||
typedef struct {
|
||||
int alloc;
|
||||
int free;
|
||||
int trace;
|
||||
list_item_t list[SET_SIZE];
|
||||
} set_t;
|
||||
|
||||
set_t *setInit(void);
|
||||
int setAdd(set_t * set, ITEM_TYPE item);
|
||||
int setDel(set_t * set, ITEM_TYPE item);
|
||||
int setFirst(set_t * set, ITEM_TYPE * item);
|
||||
int setNext(set_t * set, ITEM_TYPE * item);
|
||||
int setDestroy(set_t * set);
|
||||
|
||||
/*
|
||||
* GLX Hardware Device Driver common code
|
||||
* Copyright (C) 1999 Wittawat Yamwong
|
||||
*
|
||||
* 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 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
|
||||
* WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
struct mem_block_t {
|
||||
struct mem_block_t *next;
|
||||
struct mem_block_t *heap;
|
||||
int ofs, size;
|
||||
int align;
|
||||
unsigned int free:1;
|
||||
unsigned int reserved:1;
|
||||
};
|
||||
typedef struct mem_block_t TMemBlock;
|
||||
typedef struct mem_block_t *PMemBlock;
|
||||
|
||||
/* a heap is just the first block in a chain */
|
||||
typedef struct mem_block_t memHeap_t;
|
||||
|
||||
static __inline__ int mmBlockSize(PMemBlock b)
|
||||
{
|
||||
return b->size;
|
||||
}
|
||||
|
||||
static __inline__ int mmOffset(PMemBlock b)
|
||||
{
|
||||
return b->ofs;
|
||||
}
|
||||
|
||||
static __inline__ void mmMarkReserved(PMemBlock b)
|
||||
{
|
||||
b->reserved = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* input: total size in bytes
|
||||
* return: a heap pointer if OK, NULL if error
|
||||
*/
|
||||
memHeap_t *mmInit(int ofs, int size);
|
||||
|
||||
/*
|
||||
* Allocate 'size' bytes with 2^align2 bytes alignment,
|
||||
* restrict the search to free memory after 'startSearch'
|
||||
* depth and back buffers should be in different 4mb banks
|
||||
* to get better page hits if possible
|
||||
* input: size = size of block
|
||||
* align2 = 2^align2 bytes alignment
|
||||
* startSearch = linear offset from start of heap to begin search
|
||||
* return: pointer to the allocated block, 0 if error
|
||||
*/
|
||||
PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch);
|
||||
|
||||
/*
|
||||
* Returns 1 if the block 'b' is part of the heap 'heap'
|
||||
*/
|
||||
int mmBlockInHeap(PMemBlock heap, PMemBlock b);
|
||||
|
||||
/*
|
||||
* Free block starts at offset
|
||||
* input: pointer to a block
|
||||
* return: 0 if OK, -1 if error
|
||||
*/
|
||||
int mmFreeMem(PMemBlock b);
|
||||
|
||||
/* For debuging purpose. */
|
||||
void mmDumpMemInfo(memHeap_t * mmInit);
|
||||
|
||||
#endif /* __SIS_DS_H__ */
|
|
@ -0,0 +1,423 @@
|
|||
/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
|
||||
* Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
|
||||
*
|
||||
* Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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:
|
||||
* Sung-Ching Lin <sclin@sis.com.tw>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/sis_mm.c,v 1.9 2006/04/09 20:45:45 anholt Exp $");
|
||||
*/
|
||||
|
||||
#if defined(__linux__) && defined(CONFIG_FB_SIS)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
#include <video/sisfb.h>
|
||||
#else
|
||||
#include <linux/sisfb.h>
|
||||
#endif
|
||||
#endif
|
||||
#include "drmP.h"
|
||||
#include "sis_drm.h"
|
||||
#include "sis_drv.h"
|
||||
#include "sis_ds.h"
|
||||
|
||||
#define MAX_CONTEXT 100
|
||||
#define VIDEO_TYPE 0
|
||||
#define AGP_TYPE 1
|
||||
|
||||
typedef struct {
|
||||
int used;
|
||||
int context;
|
||||
set_t *sets[2]; /* 0 for video, 1 for AGP */
|
||||
} sis_context_t;
|
||||
|
||||
static sis_context_t global_ppriv[MAX_CONTEXT];
|
||||
|
||||
static int add_alloc_set(int context, int type, unsigned int val)
|
||||
{
|
||||
int i, retval = 0;
|
||||
|
||||
for (i = 0; i < MAX_CONTEXT; i++) {
|
||||
if (global_ppriv[i].used && global_ppriv[i].context == context) {
|
||||
retval = setAdd(global_ppriv[i].sets[type], val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int del_alloc_set(int context, int type, unsigned int val)
|
||||
{
|
||||
int i, retval = 0;
|
||||
|
||||
for (i = 0; i < MAX_CONTEXT; i++) {
|
||||
if (global_ppriv[i].used && global_ppriv[i].context == context) {
|
||||
retval = setDel(global_ppriv[i].sets[type], val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* fb management via fb device */
|
||||
#if defined(__linux__) && defined(CONFIG_FB_SIS)
|
||||
|
||||
static int sis_fb_init(DRM_IOCTL_ARGS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sis_fb_alloc(DRM_IOCTL_ARGS)
|
||||
{
|
||||
drm_sis_mem_t fb;
|
||||
struct sis_memreq req;
|
||||
drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
|
||||
int retval = 0;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
|
||||
|
||||
req.size = fb.size;
|
||||
sis_malloc(&req);
|
||||
if (req.offset) {
|
||||
/* TODO */
|
||||
fb.offset = req.offset;
|
||||
fb.free = req.offset;
|
||||
if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
|
||||
DRM_DEBUG("adding to allocation set fails\n");
|
||||
sis_free(req.offset);
|
||||
retval = DRM_ERR(EINVAL);
|
||||
}
|
||||
} else {
|
||||
fb.offset = 0;
|
||||
fb.size = 0;
|
||||
fb.free = 0;
|
||||
}
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
|
||||
|
||||
DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int sis_fb_free(DRM_IOCTL_ARGS)
|
||||
{
|
||||
drm_sis_mem_t fb;
|
||||
int retval = 0;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
|
||||
|
||||
if (!fb.free)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
|
||||
retval = DRM_ERR(EINVAL);
|
||||
sis_free(fb.free);
|
||||
|
||||
DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Called by the X Server to initialize the FB heap. Allocations will fail
|
||||
* unless this is called. Offset is the beginning of the heap from the
|
||||
* framebuffer offset (MaxXFBMem in XFree86).
|
||||
*
|
||||
* Memory layout according to Thomas Winischofer:
|
||||
* |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
|
||||
*
|
||||
* X driver/sisfb HW- Command-
|
||||
* framebuffer memory DRI heap Cursor queue
|
||||
*/
|
||||
static int sis_fb_init(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_sis_private_t *dev_priv = dev->dev_private;
|
||||
drm_sis_fb_t fb;
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
|
||||
|
||||
if (dev_priv == NULL) {
|
||||
dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
dev_priv = dev->dev_private;
|
||||
if (dev_priv == NULL)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (dev_priv->FBHeap != NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
dev_priv->FBHeap = mmInit(fb.offset, fb.size);
|
||||
|
||||
DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sis_fb_alloc(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_sis_private_t *dev_priv = dev->dev_private;
|
||||
drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
|
||||
drm_sis_mem_t fb;
|
||||
PMemBlock block;
|
||||
int retval = 0;
|
||||
|
||||
if (dev_priv == NULL || dev_priv->FBHeap == NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
|
||||
|
||||
block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
|
||||
if (block) {
|
||||
/* TODO */
|
||||
fb.offset = block->ofs;
|
||||
fb.free = (unsigned long)block;
|
||||
if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
|
||||
DRM_DEBUG("adding to allocation set fails\n");
|
||||
mmFreeMem((PMemBlock) fb.free);
|
||||
retval = DRM_ERR(EINVAL);
|
||||
}
|
||||
} else {
|
||||
fb.offset = 0;
|
||||
fb.size = 0;
|
||||
fb.free = 0;
|
||||
}
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
|
||||
|
||||
DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int sis_fb_free(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_sis_private_t *dev_priv = dev->dev_private;
|
||||
drm_sis_mem_t fb;
|
||||
|
||||
if (dev_priv == NULL || dev_priv->FBHeap == NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
|
||||
|
||||
if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free))
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
|
||||
return DRM_ERR(EINVAL);
|
||||
mmFreeMem((PMemBlock) fb.free);
|
||||
|
||||
DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* agp memory management */
|
||||
|
||||
static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_sis_private_t *dev_priv = dev->dev_private;
|
||||
drm_sis_agp_t agp;
|
||||
|
||||
if (dev_priv == NULL) {
|
||||
dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
|
||||
DRM_MEM_DRIVER);
|
||||
dev_priv = dev->dev_private;
|
||||
if (dev_priv == NULL)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (dev_priv->AGPHeap != NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
|
||||
sizeof(agp));
|
||||
|
||||
dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
|
||||
|
||||
DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_sis_private_t *dev_priv = dev->dev_private;
|
||||
drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
|
||||
drm_sis_mem_t agp;
|
||||
PMemBlock block;
|
||||
int retval = 0;
|
||||
|
||||
if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp));
|
||||
|
||||
block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
|
||||
if (block) {
|
||||
/* TODO */
|
||||
agp.offset = block->ofs;
|
||||
agp.free = (unsigned long)block;
|
||||
if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
|
||||
DRM_DEBUG("adding to allocation set fails\n");
|
||||
mmFreeMem((PMemBlock) agp.free);
|
||||
retval = -1;
|
||||
}
|
||||
} else {
|
||||
agp.offset = 0;
|
||||
agp.size = 0;
|
||||
agp.free = 0;
|
||||
}
|
||||
|
||||
DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp));
|
||||
|
||||
DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int sis_ioctl_agp_free(DRM_IOCTL_ARGS)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_sis_private_t *dev_priv = dev->dev_private;
|
||||
drm_sis_mem_t agp;
|
||||
|
||||
if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data,
|
||||
sizeof(agp));
|
||||
|
||||
if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free))
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
mmFreeMem((PMemBlock) agp.free);
|
||||
if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
|
||||
return DRM_ERR(EINVAL);
|
||||
|
||||
DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sis_init_context(struct drm_device *dev, int context)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CONTEXT; i++) {
|
||||
if (global_ppriv[i].used &&
|
||||
(global_ppriv[i].context == context))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= MAX_CONTEXT) {
|
||||
for (i = 0; i < MAX_CONTEXT; i++) {
|
||||
if (!global_ppriv[i].used) {
|
||||
global_ppriv[i].context = context;
|
||||
global_ppriv[i].used = 1;
|
||||
global_ppriv[i].sets[0] = setInit();
|
||||
global_ppriv[i].sets[1] = setInit();
|
||||
DRM_DEBUG("init allocation set, socket=%d, "
|
||||
"context = %d\n", i, context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
|
||||
(global_ppriv[i].sets[1] == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sis_final_context(struct drm_device *dev, int context)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CONTEXT; i++) {
|
||||
if (global_ppriv[i].used &&
|
||||
(global_ppriv[i].context == context))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < MAX_CONTEXT) {
|
||||
set_t *set;
|
||||
ITEM_TYPE item;
|
||||
int retval;
|
||||
|
||||
DRM_DEBUG("find socket %d, context = %d\n", i, context);
|
||||
|
||||
/* Video Memory */
|
||||
set = global_ppriv[i].sets[0];
|
||||
retval = setFirst(set, &item);
|
||||
while (retval) {
|
||||
DRM_DEBUG("free video memory 0x%lx\n", item);
|
||||
#if defined(__linux__) && defined(CONFIG_FB_SIS)
|
||||
sis_free(item);
|
||||
#else
|
||||
mmFreeMem((PMemBlock) item);
|
||||
#endif
|
||||
retval = setNext(set, &item);
|
||||
}
|
||||
setDestroy(set);
|
||||
|
||||
/* AGP Memory */
|
||||
set = global_ppriv[i].sets[1];
|
||||
retval = setFirst(set, &item);
|
||||
while (retval) {
|
||||
DRM_DEBUG("free agp memory 0x%lx\n", item);
|
||||
mmFreeMem((PMemBlock) item);
|
||||
retval = setNext(set, &item);
|
||||
}
|
||||
setDestroy(set);
|
||||
|
||||
global_ppriv[i].used = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
drm_ioctl_desc_t sis_ioctls[] = {
|
||||
[DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
|
||||
[DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH},
|
||||
[DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}
|
||||
};
|
||||
|
||||
int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
|
|
@ -0,0 +1,127 @@
|
|||
/* tdfx_drv.c -- tdfx driver -*- linux-c -*-
|
||||
* Created: Thu Oct 7 10:38:32 1999 by faith@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Daryll Strauss <daryll@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/tdfx_drv.c,v 1.10 2005/12/20 22:44:36 jhb Exp $");
|
||||
*/
|
||||
|
||||
#include "tdfx_drv.h"
|
||||
#include "drmP.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t tdfx_pciidlist[] = {
|
||||
tdfx_PCI_IDS
|
||||
};
|
||||
|
||||
static void tdfx_configure(drm_device_t *dev)
|
||||
{
|
||||
dev->driver.buf_priv_size = 1; /* No dev_priv */
|
||||
|
||||
dev->driver.max_ioctl = 0;
|
||||
|
||||
dev->driver.name = DRIVER_NAME;
|
||||
dev->driver.desc = DRIVER_DESC;
|
||||
dev->driver.date = DRIVER_DATE;
|
||||
dev->driver.major = DRIVER_MAJOR;
|
||||
dev->driver.minor = DRIVER_MINOR;
|
||||
dev->driver.patchlevel = DRIVER_PATCHLEVEL;
|
||||
|
||||
dev->driver.use_mtrr = 1;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
tdfx_probe(device_t dev)
|
||||
{
|
||||
return drm_probe(dev, tdfx_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
tdfx_attach(device_t nbdev)
|
||||
{
|
||||
drm_device_t *dev = device_get_softc(nbdev);
|
||||
|
||||
bzero(dev, sizeof(drm_device_t));
|
||||
tdfx_configure(dev);
|
||||
return drm_attach(nbdev, tdfx_pciidlist);
|
||||
}
|
||||
|
||||
static device_method_t tdfx_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, tdfx_probe),
|
||||
DEVMETHOD(device_attach, tdfx_attach),
|
||||
DEVMETHOD(device_detach, drm_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t tdfx_driver = {
|
||||
"drm",
|
||||
tdfx_methods,
|
||||
sizeof(drm_device_t)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(tdfx, vgapci, tdfx_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(tdfx, pci, tdfx_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(tdfx, drm, 1, 1, 1);
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
static int
|
||||
tdfxdrm_probe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
return drm_probe(pa, tdfx_pciidlist);
|
||||
}
|
||||
|
||||
static void
|
||||
tdfxdrm_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
drm_device_t *dev = (drm_device_t *)self;
|
||||
|
||||
tdfx_configure(dev);
|
||||
return drm_attach(self, pa, tdfx_pciidlist);
|
||||
}
|
||||
|
||||
CFATTACH_DECL(tdfxdrm, sizeof(drm_device_t), tdfxdrm_probe, tdfxdrm_attach,
|
||||
drm_detach, drm_activate);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,52 @@
|
|||
/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
|
||||
* Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
/*
|
||||
__FBSDID("$FreeBSD: src/sys/dev/drm/tdfx_drv.h,v 1.2 2005/11/28 23:13:55 anholt Exp $");
|
||||
*/
|
||||
|
||||
#ifndef __TDFX_H__
|
||||
#define __TDFX_H__
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
|
||||
#define DRIVER_AUTHOR "VA Linux Systems Inc."
|
||||
|
||||
#define DRIVER_NAME "tdfx"
|
||||
#define DRIVER_DESC "3dfx Banshee/Voodoo3+"
|
||||
#define DRIVER_DATE "20010216"
|
||||
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 0
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.pci,v 1.278 2007/03/20 05:50:35 garbled Exp $
|
||||
# $NetBSD: files.pci,v 1.279 2007/03/20 18:05:31 drochner Exp $
|
||||
#
|
||||
# Config file and device description for machine-independent PCI code.
|
||||
# Included by ports that need it. Requires that the SCSI files be
|
||||
|
@ -862,3 +862,58 @@ attach mskc at pci
|
|||
device msk: ether, ifnet, arp, mii
|
||||
attach msk at mskc
|
||||
file dev/pci/if_msk.c mskc | msk
|
||||
|
||||
device i915drm: drmbase
|
||||
attach i915drm at drm
|
||||
file dev/pci/drm/i915_drv.c i915drm
|
||||
file dev/pci/drm/i915_dma.c i915drm
|
||||
file dev/pci/drm/i915_irq.c i915drm
|
||||
file dev/pci/drm/i915_mem.c i915drm
|
||||
|
||||
device mach64drm: drmbase
|
||||
attach mach64drm at drm
|
||||
file dev/pci/drm/mach64_dma.c mach64drm
|
||||
file dev/pci/drm/mach64_drv.c mach64drm
|
||||
file dev/pci/drm/mach64_irq.c mach64drm
|
||||
file dev/pci/drm/mach64_state.c mach64drm
|
||||
|
||||
device mgadrm: drmbase
|
||||
attach mgadrm at drm
|
||||
file dev/pci/drm/mga_dma.c mgadrm
|
||||
file dev/pci/drm/mga_drv.c mgadrm
|
||||
file dev/pci/drm/mga_irq.c mgadrm
|
||||
file dev/pci/drm/mga_state.c mgadrm
|
||||
file dev/pci/drm/mga_warp.c mgadrm
|
||||
|
||||
device r128drm: drmbase
|
||||
attach r128drm at drm
|
||||
file dev/pci/drm/ati_pcigart.c r128drm | radeondrm
|
||||
file dev/pci/drm/r128_cce.c r128drm
|
||||
file dev/pci/drm/r128_drv.c r128drm
|
||||
file dev/pci/drm/r128_irq.c r128drm
|
||||
file dev/pci/drm/r128_state.c r128drm
|
||||
|
||||
device radeondrm: drmbase
|
||||
attach radeondrm at drm
|
||||
file dev/pci/drm/r300_cmdbuf.c radeondrm
|
||||
file dev/pci/drm/radeon_cp.c radeondrm
|
||||
file dev/pci/drm/radeon_drv.c radeondrm
|
||||
file dev/pci/drm/radeon_irq.c radeondrm
|
||||
file dev/pci/drm/radeon_mem.c radeondrm
|
||||
file dev/pci/drm/radeon_state.c radeondrm
|
||||
|
||||
device savagedrm: drmbase
|
||||
attach savagedrm at drm
|
||||
file dev/pci/drm/savage_bci.c savagedrm
|
||||
file dev/pci/drm/savage_drv.c savagedrm
|
||||
file dev/pci/drm/savage_state.c savagedrm
|
||||
|
||||
device sisdrm: drmbase
|
||||
attach sisdrm at drm
|
||||
file dev/pci/drm/sis_drv.c sisdrm
|
||||
file dev/pci/drm/sis_ds.c sisdrm
|
||||
file dev/pci/drm/sis_mm.c sisdrm
|
||||
|
||||
device tdfxdrm: drmbase
|
||||
attach tdfxdrm at drm
|
||||
file dev/pci/drm/tdfx_drv.c tdfxdrm
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vga_pci.c,v 1.31 2007/03/04 06:02:26 christos Exp $ */
|
||||
/* $NetBSD: vga_pci.c,v 1.32 2007/03/20 18:05:31 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
|
||||
|
@ -28,7 +28,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vga_pci.c,v 1.31 2007/03/04 06:02:26 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vga_pci.c,v 1.32 2007/03/20 18:05:31 drochner Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -214,6 +214,8 @@ vga_pci_attach(struct device *parent, struct device *self, void *aux)
|
|||
|
||||
vga_common_attach(sc, pa->pa_iot, pa->pa_memt, WSDISPLAY_TYPE_PCIVGA,
|
||||
vga_pci_lookup_quirks(pa), &vga_pci_funcs);
|
||||
|
||||
config_found_ia(self, "drm", aux, vga_drm_print);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -225,6 +227,15 @@ vga_pci_cnattach(bus_space_tag_t iot, bus_space_tag_t memt,
|
|||
return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0));
|
||||
}
|
||||
|
||||
int
|
||||
vga_drm_print(void *aux, const char *pnp)
|
||||
{
|
||||
if (pnp)
|
||||
aprint_normal("direct rendering for %s", pnp);
|
||||
return (UNSUPP);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vga_pci_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vga_pcivar.h,v 1.4 2005/12/11 12:22:51 christos Exp $ */
|
||||
/* $NetBSD: vga_pcivar.h,v 1.5 2007/03/20 18:05:31 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
|
||||
|
@ -35,3 +35,5 @@
|
|||
|
||||
int vga_pci_cnattach(bus_space_tag_t, bus_space_tag_t,
|
||||
pci_chipset_tag_t, int, int, int);
|
||||
|
||||
int vga_drm_print(void *aux, const char *pnp);
|
||||
|
|
Loading…
Reference in New Issue