summaryrefslogtreecommitdiffstats
path: root/sys/dev/drm
diff options
context:
space:
mode:
authoranholt <anholt@FreeBSD.org>2002-04-27 20:47:57 +0000
committeranholt <anholt@FreeBSD.org>2002-04-27 20:47:57 +0000
commit682fe32ace5d21d6e0400fcfc7426bc6ae04c124 (patch)
tree2e73a21383876a4e751630f3059c8690aecfb78a /sys/dev/drm
parent6818945234fbb5686fb3e963d4f172c2c44fdbf1 (diff)
downloadFreeBSD-src-682fe32ace5d21d6e0400fcfc7426bc6ae04c124.zip
FreeBSD-src-682fe32ace5d21d6e0400fcfc7426bc6ae04c124.tar.gz
Add the code for the DRM, based on the code from the drm-kmod port.
This is not hooked up yet, that will come later. Approved by: des
Diffstat (limited to 'sys/dev/drm')
-rw-r--r--sys/dev/drm/drm.h497
-rw-r--r--sys/dev/drm/drmP.h723
-rw-r--r--sys/dev/drm/drm_agpsupport.h330
-rw-r--r--sys/dev/drm/drm_auth.h177
-rw-r--r--sys/dev/drm/drm_bufs.h1284
-rw-r--r--sys/dev/drm/drm_context.h780
-rw-r--r--sys/dev/drm/drm_dma.h679
-rw-r--r--sys/dev/drm/drm_drawable.h52
-rw-r--r--sys/dev/drm/drm_drv.h1455
-rw-r--r--sys/dev/drm/drm_fops.h364
-rw-r--r--sys/dev/drm/drm_init.h120
-rw-r--r--sys/dev/drm/drm_ioctl.h323
-rw-r--r--sys/dev/drm/drm_linux.h147
-rw-r--r--sys/dev/drm/drm_lists.h304
-rw-r--r--sys/dev/drm/drm_lock.h314
-rw-r--r--sys/dev/drm/drm_memory.h595
-rw-r--r--sys/dev/drm/drm_os_freebsd.h382
-rw-r--r--sys/dev/drm/drm_scatter.h239
-rw-r--r--sys/dev/drm/drm_sysctl.h525
-rw-r--r--sys/dev/drm/drm_vm.h85
-rw-r--r--sys/dev/drm/gamma.h95
-rw-r--r--sys/dev/drm/gamma_dma.c647
-rw-r--r--sys/dev/drm/gamma_drv.c125
-rw-r--r--sys/dev/drm/gamma_drv.h105
-rw-r--r--sys/dev/drm/i810_drm.h203
-rw-r--r--sys/dev/drm/mga.h69
-rw-r--r--sys/dev/drm/mga_dma.c851
-rw-r--r--sys/dev/drm/mga_drm.h312
-rw-r--r--sys/dev/drm/mga_drv.c137
-rw-r--r--sys/dev/drm/mga_drv.h640
-rw-r--r--sys/dev/drm/mga_state.c1068
-rw-r--r--sys/dev/drm/mga_ucode.h11647
-rw-r--r--sys/dev/drm/mga_warp.c212
-rw-r--r--sys/dev/drm/r128.h83
-rw-r--r--sys/dev/drm/r128_cce.c1056
-rw-r--r--sys/dev/drm/r128_drm.h289
-rw-r--r--sys/dev/drm/r128_drv.c167
-rw-r--r--sys/dev/drm/r128_drv.h548
-rw-r--r--sys/dev/drm/r128_state.c1576
-rw-r--r--sys/dev/drm/radeon.h83
-rw-r--r--sys/dev/drm/radeon_cp.c1458
-rw-r--r--sys/dev/drm/radeon_drm.h335
-rw-r--r--sys/dev/drm/radeon_drv.c165
-rw-r--r--sys/dev/drm/radeon_drv.h741
-rw-r--r--sys/dev/drm/radeon_state.c1467
-rw-r--r--sys/dev/drm/sis_drm.h33
-rw-r--r--sys/dev/drm/tdfx.h44
-rw-r--r--sys/dev/drm/tdfx_drv.c152
48 files changed, 33683 insertions, 0 deletions
diff --git a/sys/dev/drm/drm.h b/sys/dev/drm/drm.h
new file mode 100644
index 0000000..c0fa7af
--- /dev/null
+++ b/sys/dev/drm/drm.h
@@ -0,0 +1,497 @@
+/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan 4 10:05:05 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>
+ *
+ * Acknowledgements:
+ * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic cmpxchg.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DRM_H_
+#define _DRM_H_
+
+#ifdef __linux__
+#include <linux/config.h>
+#include <asm/ioctl.h> /* For _IO* macros */
+#define DRM_IOCTL_NR(n) _IOC_NR(n)
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include <sys/ioccom.h>
+#define DRM_IOCTL_NR(n) ((n) & 0xff)
+#endif /* __FreeBSD__ */
+
+#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)
+#define DRM_MAJOR 226
+#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 50 /* How much system ram can we lock? */
+
+#define _DRM_LOCK_HELD 0x80000000 /* Hardware lock is held */
+#define _DRM_LOCK_CONT 0x40000000 /* 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))
+
+typedef unsigned long drm_handle_t;
+typedef unsigned int drm_context_t;
+typedef unsigned int drm_drawable_t;
+typedef unsigned int drm_magic_t;
+
+/* Warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well */
+
+typedef struct drm_clip_rect {
+ unsigned short x1;
+ unsigned short y1;
+ unsigned short x2;
+ unsigned short y2;
+} drm_clip_rect_t;
+
+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;
+
+/* Seperate include files for the i810/mga/r128 specific structures */
+#include "dev/drm/mga_drm.h"
+#include "dev/drm/i810_drm.h"
+#include "dev/drm/r128_drm.h"
+#include "dev/drm/radeon_drm.h"
+#include "dev/drm/sis_drm.h"
+
+typedef struct drm_version {
+ int version_major; /* Major version */
+ int version_minor; /* Minor version */
+ int version_patchlevel;/* Patch level */
+ size_t name_len; /* Length of name buffer */
+ char *name; /* Name of driver */
+ size_t date_len; /* Length of date buffer */
+ char *date; /* User-space buffer to hold date */
+ size_t desc_len; /* Length of desc buffer */
+ char *desc; /* User-space buffer to hold desc */
+} drm_version_t;
+
+typedef struct drm_unique {
+ size_t unique_len; /* Length of unique */
+ char *unique; /* Unique name for driver instantiation */
+} drm_unique_t;
+
+typedef struct drm_list {
+ int count; /* Length of user-space structures */
+ drm_version_t *version;
+} drm_list_t;
+
+typedef struct drm_block {
+ int unused;
+} drm_block_t;
+
+typedef struct drm_control {
+ enum {
+ DRM_ADD_COMMAND,
+ DRM_RM_COMMAND,
+ DRM_INST_HANDLER,
+ DRM_UNINST_HANDLER
+ } func;
+ int irq;
+} drm_control_t;
+
+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_map_type_t;
+
+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;
+
+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;
+
+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;
+
+typedef struct drm_stats {
+ unsigned long count;
+ struct {
+ unsigned long value;
+ drm_stat_type_t type;
+ } data[15];
+} drm_stats_t;
+
+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;
+
+typedef struct drm_lock {
+ int context;
+ drm_lock_flags_t flags;
+} drm_lock_t;
+
+typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
+ /* 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;
+
+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 */
+ } flags;
+ unsigned long agp_start; /* Start address of where the agp buffers
+ * are in the agp aperture */
+} drm_buf_desc_t;
+
+typedef struct drm_buf_info {
+ int count; /* Entries in list */
+ drm_buf_desc_t *list;
+} drm_buf_info_t;
+
+typedef struct drm_buf_free {
+ int count;
+ int *list;
+} drm_buf_free_t;
+
+typedef struct drm_buf_pub {
+ int idx; /* Index into master buflist */
+ int total; /* Buffer size */
+ int used; /* Amount of buffer in use (for DMA) */
+ void *address; /* Address of buffer */
+} drm_buf_pub_t;
+
+typedef struct drm_buf_map {
+ int count; /* Length of buflist */
+ void *virtual; /* Mmaped area in user-virtual */
+ drm_buf_pub_t *list; /* Buffer information */
+} drm_buf_map_t;
+
+typedef struct drm_dma {
+ /* Indices here refer to the offset into
+ buflist in drm_buf_get_t. */
+ int context; /* Context handle */
+ int send_count; /* Number of buffers to send */
+ int *send_indices; /* List of handles to buffers */
+ int *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 *request_indices; /* Buffer information */
+ int *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;
+
+typedef struct drm_ctx {
+ drm_context_t handle;
+ drm_ctx_flags_t flags;
+} drm_ctx_t;
+
+typedef struct drm_ctx_res {
+ int count;
+ drm_ctx_t *contexts;
+} drm_ctx_res_t;
+
+typedef struct drm_draw {
+ drm_drawable_t handle;
+} drm_draw_t;
+
+typedef struct drm_auth {
+ drm_magic_t magic;
+} drm_auth_t;
+
+typedef struct drm_irq_busid {
+ int irq;
+ int busnum;
+ int devnum;
+ int funcnum;
+} drm_irq_busid_t;
+
+typedef struct drm_agp_mode {
+ unsigned long mode;
+} drm_agp_mode_t;
+
+ /* For drm_agp_alloc -- allocated a buffer */
+typedef struct drm_agp_buffer {
+ unsigned long size; /* In bytes -- will round to page boundary */
+ unsigned long handle; /* Used for BIND/UNBIND ioctls */
+ unsigned long type; /* Type of memory to allocate */
+ unsigned long physical; /* Physical used by i810 */
+} drm_agp_buffer_t;
+
+ /* For drm_agp_bind */
+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;
+
+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;
+
+ /* PCI information */
+ unsigned short id_vendor;
+ unsigned short id_device;
+} drm_agp_info_t;
+
+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;
+
+#define DRM_IOCTL_BASE 'd'
+#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
+#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
+#define DRM_IOW(nr,size) _IOW(DRM_IOCTL_BASE,nr,size)
+#define DRM_IOWR(nr,size) _IOWR(DRM_IOCTL_BASE,nr,size)
+
+
+#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_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)
+
+/* MGA specific ioctls */
+#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
+#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
+#define DRM_IOCTL_MGA_RESET DRM_IO( 0x42)
+#define DRM_IOCTL_MGA_SWAP DRM_IO( 0x43)
+#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x44, drm_mga_clear_t)
+#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x45, drm_mga_vertex_t)
+#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
+#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t)
+#define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t)
+
+/* i810 specific ioctls */
+#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
+#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
+#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t)
+#define DRM_IOCTL_I810_FLUSH DRM_IO( 0x43)
+#define DRM_IOCTL_I810_GETAGE DRM_IO( 0x44)
+#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP DRM_IO( 0x46)
+#define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t)
+#define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48)
+
+/* Rage 128 specific ioctls */
+#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
+#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41)
+#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t)
+#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43)
+#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44)
+#define DRM_IOCTL_R128_RESET DRM_IO( 0x46)
+#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47)
+#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t)
+#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t)
+#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t)
+#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t)
+#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t)
+#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t)
+#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t)
+#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t)
+
+/* Radeon specific ioctls */
+#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t)
+#define DRM_IOCTL_RADEON_CP_START DRM_IO( 0x41)
+#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( 0x42, drm_radeon_cp_stop_t)
+#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43)
+#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44)
+#define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45)
+#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t)
+#define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47)
+#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t)
+#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t)
+#define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t)
+#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t)
+#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t)
+#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t)
+
+/* SiS specific ioctls */
+
+#define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t)
+#define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t)
+#define SIS_IOCTL_AGP_INIT DRM_IOWR(0x53, drm_sis_agp_t)
+#define SIS_IOCTL_AGP_ALLOC DRM_IOWR(0x54, drm_sis_mem_t)
+#define SIS_IOCTL_AGP_FREE DRM_IOW( 0x55, drm_sis_mem_t)
+#define SIS_IOCTL_FLIP DRM_IOW( 0x48, drm_sis_flip_t)
+#define SIS_IOCTL_FLIP_INIT DRM_IO( 0x49)
+#define SIS_IOCTL_FLIP_FINAL DRM_IO( 0x50)
+
+#endif
diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
new file mode 100644
index 0000000..00b0eb9
--- /dev/null
+++ b/sys/dev/drm/drmP.h
@@ -0,0 +1,723 @@
+/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan 4 10:05:05 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DRM_P_H_
+#define _DRM_P_H_
+
+#if defined(_KERNEL) || defined(__KERNEL__)
+
+/* DRM template customization defaults
+ */
+#ifndef __HAVE_AGP
+#define __HAVE_AGP 0
+#endif
+#ifndef __HAVE_MTRR
+#define __HAVE_MTRR 0
+#endif
+#ifndef __HAVE_CTX_BITMAP
+#define __HAVE_CTX_BITMAP 0
+#endif
+#ifndef __HAVE_DMA
+#define __HAVE_DMA 0
+#endif
+#ifndef __HAVE_DMA_IRQ
+#define __HAVE_DMA_IRQ 0
+#endif
+#ifndef __HAVE_DMA_WAITLIST
+#define __HAVE_DMA_WAITLIST 0
+#endif
+#ifndef __HAVE_DMA_FREELIST
+#define __HAVE_DMA_FREELIST 0
+#endif
+#ifndef __HAVE_DMA_HISTOGRAM
+#define __HAVE_DMA_HISTOGRAM 0
+#endif
+
+#define DRM_DEBUG_CODE 0 /* Include debugging code (if > 1, then
+ also include looping detection. */
+
+typedef struct drm_device drm_device_t;
+typedef struct drm_file drm_file_t;
+
+/* There's undoubtably more of this file to go into these OS dependent ones. */
+#ifdef __linux__
+#include "dev/drm/drm_os_linux.h"
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+#include "dev/drm/drm_os_freebsd.h"
+#endif /* __FreeBSD__ */
+
+#include "dev/drm/drm.h"
+
+/* Begin the DRM... */
+
+#define DRM_HASH_SIZE 16 /* Size of key hash table */
+#define DRM_KERNEL_CONTEXT 0 /* Change drm_resctx if changed */
+#define DRM_RESERVED_CONTEXTS 1 /* Change drm_resctx if changed */
+#define DRM_LOOPING_LIMIT 5000000
+#define DRM_BSZ 1024 /* Buffer size for /dev/drm? output */
+#define DRM_LOCK_SLICE 1 /* Time slice for lock, in jiffies */
+
+#define DRM_FLAG_DEBUG 0x01
+#define DRM_FLAG_NOCTX 0x02
+
+#define DRM_MEM_DMA 0
+#define DRM_MEM_SAREA 1
+#define DRM_MEM_DRIVER 2
+#define DRM_MEM_MAGIC 3
+#define DRM_MEM_IOCTLS 4
+#define DRM_MEM_MAPS 5
+#define DRM_MEM_VMAS 6
+#define DRM_MEM_BUFS 7
+#define DRM_MEM_SEGS 8
+#define DRM_MEM_PAGES 9
+#define DRM_MEM_FILES 10
+#define DRM_MEM_QUEUES 11
+#define DRM_MEM_CMDS 12
+#define DRM_MEM_MAPPINGS 13
+#define DRM_MEM_BUFLISTS 14
+#define DRM_MEM_AGPLISTS 15
+#define DRM_MEM_TOTALAGP 16
+#define DRM_MEM_BOUNDAGP 17
+#define DRM_MEM_CTXBITMAP 18
+#define DRM_MEM_STUB 19
+#define DRM_MEM_SGLISTS 20
+
+#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
+
+ /* Backward compatibility section */
+ /* _PAGE_WT changed to _PAGE_PWT in 2.2.6 */
+#ifndef _PAGE_PWT
+#define _PAGE_PWT _PAGE_WT
+#endif
+
+ /* Mapping helper macros */
+#define DRM_IOREMAP(map) \
+ (map)->handle = DRM(ioremap)( (map)->offset, (map)->size )
+
+#define DRM_IOREMAPFREE(map) \
+ do { \
+ if ( (map)->handle && (map)->size ) \
+ DRM(ioremapfree)( (map)->handle, (map)->size ); \
+ } while (0)
+
+ /* Internal types and structures */
+#define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
+#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
+#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
+#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
+
+#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \
+ (_map) = (_dev)->context_sareas[_ctx]; \
+} while(0)
+
+#ifdef __linux__
+typedef int drm_ioctl_t( DRM_OS_IOCTL );
+#endif /* __linux__ */
+
+typedef struct drm_pci_list {
+ u16 vendor;
+ u16 device;
+} drm_pci_list_t;
+
+typedef struct drm_ioctl_desc {
+#ifdef __linux__
+ drm_ioctl_t *func;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ d_ioctl_t *func;
+#endif /* __FreeBSD__ */
+ int auth_needed;
+ int root_only;
+} drm_ioctl_desc_t;
+
+typedef struct drm_devstate {
+ pid_t owner; /* X server pid holding x_lock */
+
+} drm_devstate_t;
+
+typedef struct drm_magic_entry {
+ drm_magic_t magic;
+ struct drm_file *priv;
+ struct drm_magic_entry *next;
+} drm_magic_entry_t;
+
+typedef struct drm_magic_head {
+ struct drm_magic_entry *head;
+ struct drm_magic_entry *tail;
+} drm_magic_head_t;
+
+typedef struct drm_vma_entry {
+ struct vm_area_struct *vma;
+ struct drm_vma_entry *next;
+ pid_t pid;
+} drm_vma_entry_t;
+
+typedef struct drm_buf {
+ int idx; /* Index into master buflist */
+ int total; /* Buffer size */
+ int order; /* log-base-2(total) */
+ int used; /* Amount of buffer in use (for DMA) */
+ unsigned long offset; /* Byte offset (used internally) */
+ void *address; /* Address of buffer */
+ unsigned long bus_address; /* Bus address of buffer */
+ struct drm_buf *next; /* Kernel-only: used for free list */
+ __volatile__ int waiting; /* On kernel DMA queue */
+ __volatile__ int pending; /* On hardware DMA queue */
+ wait_queue_head_t dma_wait; /* Processes waiting */
+ pid_t pid; /* PID of holding process */
+ int context; /* Kernel queue for this buffer */
+ int while_locked;/* Dispatch this buffer while locked */
+ enum {
+ DRM_LIST_NONE = 0,
+ DRM_LIST_FREE = 1,
+ DRM_LIST_WAIT = 2,
+ DRM_LIST_PEND = 3,
+ DRM_LIST_PRIO = 4,
+ DRM_LIST_RECLAIM = 5
+ } list; /* Which list we're on */
+
+#if DRM_DMA_HISTOGRAM
+ cycles_t time_queued; /* Queued to kernel DMA queue */
+ cycles_t time_dispatched; /* Dispatched to hardware */
+ cycles_t time_completed; /* Completed by hardware */
+ cycles_t time_freed; /* Back on freelist */
+#endif
+
+ int dev_priv_size; /* Size of buffer private stoarge */
+ void *dev_private; /* Per-buffer private storage */
+} drm_buf_t;
+
+#if DRM_DMA_HISTOGRAM
+#define DRM_DMA_HISTOGRAM_SLOTS 9
+#define DRM_DMA_HISTOGRAM_INITIAL 10
+#define DRM_DMA_HISTOGRAM_NEXT(current) ((current)*10)
+typedef struct drm_histogram {
+ atomic_t total;
+
+ atomic_t queued_to_dispatched[DRM_DMA_HISTOGRAM_SLOTS];
+ atomic_t dispatched_to_completed[DRM_DMA_HISTOGRAM_SLOTS];
+ atomic_t completed_to_freed[DRM_DMA_HISTOGRAM_SLOTS];
+
+ atomic_t queued_to_completed[DRM_DMA_HISTOGRAM_SLOTS];
+ atomic_t queued_to_freed[DRM_DMA_HISTOGRAM_SLOTS];
+
+ atomic_t dma[DRM_DMA_HISTOGRAM_SLOTS];
+ atomic_t schedule[DRM_DMA_HISTOGRAM_SLOTS];
+ atomic_t ctx[DRM_DMA_HISTOGRAM_SLOTS];
+ atomic_t lacq[DRM_DMA_HISTOGRAM_SLOTS];
+ atomic_t lhld[DRM_DMA_HISTOGRAM_SLOTS];
+} drm_histogram_t;
+#endif
+
+ /* bufs is one longer than it has to be */
+typedef struct drm_waitlist {
+ int count; /* Number of possible buffers */
+ drm_buf_t **bufs; /* List of pointers to buffers */
+ drm_buf_t **rp; /* Read pointer */
+ drm_buf_t **wp; /* Write pointer */
+ drm_buf_t **end; /* End pointer */
+ DRM_OS_SPINTYPE read_lock;
+ DRM_OS_SPINTYPE write_lock;
+} drm_waitlist_t;
+
+typedef struct drm_freelist {
+ int initialized; /* Freelist in use */
+ atomic_t count; /* Number of free buffers */
+ drm_buf_t *next; /* End pointer */
+
+ wait_queue_head_t waiting; /* Processes waiting on free bufs */
+ int low_mark; /* Low water mark */
+ int high_mark; /* High water mark */
+ atomic_t wfh; /* If waiting for high mark */
+ DRM_OS_SPINTYPE lock;
+} drm_freelist_t;
+
+typedef struct drm_buf_entry {
+ int buf_size;
+ int buf_count;
+ drm_buf_t *buflist;
+ int seg_count;
+ int page_order;
+ unsigned long *seglist;
+
+ drm_freelist_t freelist;
+} drm_buf_entry_t;
+
+typedef struct drm_hw_lock {
+ __volatile__ unsigned int lock;
+ char padding[60]; /* Pad to cache line */
+} drm_hw_lock_t;
+
+#ifdef __linux__
+struct drm_file {
+ int authenticated;
+ int minor;
+ pid_t pid;
+ uid_t uid;
+ drm_magic_t magic;
+ unsigned long ioctl_count;
+ struct drm_file *next;
+ struct drm_file *prev;
+ struct drm_device *dev;
+ int remove_auth_on_close;
+};
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+typedef TAILQ_HEAD(drm_file_list, drm_file) drm_file_list_t;
+struct drm_file {
+ TAILQ_ENTRY(drm_file) link;
+ int authenticated;
+ int minor;
+ pid_t pid;
+ uid_t uid;
+ int refs;
+ drm_magic_t magic;
+ unsigned long ioctl_count;
+ struct drm_device *devXX;
+};
+#endif /* __FreeBSD__ */
+
+typedef struct drm_queue {
+ atomic_t use_count; /* Outstanding uses (+1) */
+ atomic_t finalization; /* Finalization in progress */
+ atomic_t block_count; /* Count of processes waiting */
+ atomic_t block_read; /* Queue blocked for reads */
+ wait_queue_head_t read_queue; /* Processes waiting on block_read */
+ atomic_t block_write; /* Queue blocked for writes */
+ wait_queue_head_t write_queue; /* Processes waiting on block_write */
+#if 1
+ atomic_t total_queued; /* Total queued statistic */
+ atomic_t total_flushed;/* Total flushes statistic */
+ atomic_t total_locks; /* Total locks statistics */
+#endif
+ drm_ctx_flags_t flags; /* Context preserving and 2D-only */
+ drm_waitlist_t waitlist; /* Pending buffers */
+ wait_queue_head_t flush_queue; /* Processes waiting until flush */
+} drm_queue_t;
+
+typedef struct drm_lock_data {
+ drm_hw_lock_t *hw_lock; /* Hardware lock */
+ pid_t pid; /* PID of lock holder (0=kernel) */
+ wait_queue_head_t lock_queue; /* Queue of blocked processes */
+ unsigned long lock_time; /* Time of last lock in jiffies */
+} drm_lock_data_t;
+
+typedef struct drm_device_dma {
+#if 0
+ /* Performance Counters */
+ atomic_t total_prio; /* Total DRM_DMA_PRIORITY */
+ atomic_t total_bytes; /* Total bytes DMA'd */
+ atomic_t total_dmas; /* Total DMA buffers dispatched */
+
+ atomic_t total_missed_dma; /* Missed drm_do_dma */
+ atomic_t total_missed_lock; /* Missed lock in drm_do_dma */
+ atomic_t total_missed_free; /* Missed drm_free_this_buffer */
+ atomic_t total_missed_sched;/* Missed drm_dma_schedule */
+
+ atomic_t total_tried; /* Tried next_buffer */
+ atomic_t total_hit; /* Sent next_buffer */
+ atomic_t total_lost; /* Lost interrupt */
+#endif
+
+ drm_buf_entry_t bufs[DRM_MAX_ORDER+1];
+ int buf_count;
+ drm_buf_t **buflist; /* Vector of pointers info bufs */
+ int seg_count;
+ int page_count;
+ unsigned long *pagelist;
+ unsigned long byte_count;
+ enum {
+ _DRM_DMA_USE_AGP = 0x01,
+ _DRM_DMA_USE_SG = 0x02
+ } flags;
+
+ /* DMA support */
+ drm_buf_t *this_buffer; /* Buffer being sent */
+ drm_buf_t *next_buffer; /* Selected buffer to send */
+ drm_queue_t *next_queue; /* Queue from which buffer selected*/
+ wait_queue_head_t waiting; /* Processes waiting on free bufs */
+} drm_device_dma_t;
+
+#if __REALLY_HAVE_AGP
+typedef struct drm_agp_mem {
+#ifdef __linux__
+ unsigned long handle;
+ agp_memory *memory;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ void *handle;
+#endif /* __FreeBSD__ */
+ unsigned long bound; /* address */
+ int pages;
+ struct drm_agp_mem *prev;
+ struct drm_agp_mem *next;
+} drm_agp_mem_t;
+
+typedef struct drm_agp_head {
+#ifdef __linux__
+ agp_kern_info agp_info;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ device_t agpdev;
+ struct agp_info info;
+#endif /* __FreeBSD__ */
+ const char *chipset;
+ drm_agp_mem_t *memory;
+ unsigned long mode;
+ int enabled;
+ int acquired;
+ unsigned long base;
+ int agp_mtrr;
+ int cant_use_aperture;
+ unsigned long page_mask;
+} drm_agp_head_t;
+#endif
+
+typedef struct drm_sg_mem {
+ unsigned long handle;
+ void *virtual;
+ int pages;
+ struct page **pagelist;
+#ifdef __linux__
+ dma_addr_t *busaddr;
+#endif /* __linux__ */
+} drm_sg_mem_t;
+
+typedef struct drm_sigdata {
+ int context;
+ drm_hw_lock_t *lock;
+} drm_sigdata_t;
+
+#ifdef __linux__
+typedef struct drm_map_list {
+ struct list_head head;
+ drm_map_t *map;
+} drm_map_list_t;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+typedef TAILQ_HEAD(drm_map_list, drm_map_list_entry) drm_map_list_t;
+typedef struct drm_map_list_entry {
+ TAILQ_ENTRY(drm_map_list_entry) link;
+ drm_map_t *map;
+} drm_map_list_entry_t;
+#endif /* __FreeBSD__ */
+
+struct drm_device {
+ const char *name; /* Simple driver name */
+ char *unique; /* Unique identifier: e.g., busid */
+ int unique_len; /* Length of unique field */
+#ifdef __linux__
+ dev_t device; /* Device number for mknod */
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ device_t device; /* Device instance from newbus */
+ dev_t devnode; /* Device number for mknod */
+#endif /* __FreeBSD__ */
+ char *devname; /* For /proc/interrupts */
+
+ int blocked; /* Blocked due to VC switch? */
+#ifdef __FreeBSD__
+ int flags; /* Flags to open(2) */
+ int writable; /* Opened with FWRITE */
+#endif /* __FreeBSD__ */
+ struct proc_dir_entry *root; /* Root for this device's entries */
+
+ /* Locks */
+#ifdef __linux__
+ spinlock_t count_lock; /* For inuse, open_count, buf_use */
+ struct semaphore struct_sem; /* For others */
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM_OS_SPINTYPE count_lock; /* For inuse, open_count, buf_use */
+ struct lock dev_lock; /* For others */
+#endif /* __FreeBSD__ */
+ /* Usage Counters */
+ int open_count; /* Outstanding files open */
+ atomic_t ioctl_count; /* Outstanding IOCTLs pending */
+ atomic_t vma_count; /* Outstanding vma areas open */
+ int buf_use; /* Buffers in use -- cannot alloc */
+ atomic_t buf_alloc; /* Buffer allocation in progress */
+
+ /* Performance counters */
+ unsigned long counters;
+ drm_stat_type_t types[15];
+ atomic_t counts[15];
+
+ /* Authentication */
+#ifdef __linux__
+ drm_file_t *file_first;
+ drm_file_t *file_last;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_file_list_t files;
+#endif /* __FreeBSD__ */
+ drm_magic_head_t magiclist[DRM_HASH_SIZE];
+
+ /* Memory management */
+ drm_map_list_t *maplist; /* Linked list of regions */
+ int map_count; /* Number of mappable regions */
+
+ drm_map_t **context_sareas;
+ int max_context;
+
+ drm_vma_entry_t *vmalist; /* List of vmas (for debugging) */
+ drm_lock_data_t lock; /* Information on hardware lock */
+
+ /* DMA queues (contexts) */
+ int queue_count; /* Number of active DMA queues */
+ int queue_reserved; /* Number of reserved DMA queues */
+ int queue_slots; /* Actual length of queuelist */
+ drm_queue_t **queuelist; /* Vector of pointers to DMA queues */
+ drm_device_dma_t *dma; /* Optional pointer for DMA support */
+
+ /* Context support */
+ int irq; /* Interrupt used by board */
+#ifdef __FreeBSD__
+ struct resource *irqr; /* Resource for interrupt used by board */
+ void *irqh; /* Handle from bus_setup_intr */
+#endif /* __FreeBSD__ */
+ __volatile__ long context_flag; /* Context swapping flag */
+ __volatile__ long interrupt_flag; /* Interruption handler flag */
+ __volatile__ long dma_flag; /* DMA dispatch flag */
+#ifdef __linux__
+ struct timer_list timer; /* Timer for delaying ctx switch */
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ struct callout timer; /* Timer for delaying ctx switch */
+#endif /* __FreeBSD__ */
+ wait_queue_head_t context_wait; /* Processes waiting on ctx switch */
+ int last_checked; /* Last context checked for DMA */
+ int last_context; /* Last current context */
+ unsigned long last_switch; /* jiffies at last context switch */
+#ifdef __linux__
+ struct tq_struct tq;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#if __FreeBSD_version >= 400005
+ struct task task;
+#endif
+#endif /* __FreeBSD__ */
+ cycles_t ctx_start;
+ cycles_t lck_start;
+#if __HAVE_DMA_HISTOGRAM
+ drm_histogram_t histo;
+#endif
+
+ /* Callback to X server for context switch
+ and for heavy-handed reset. */
+ char buf[DRM_BSZ]; /* Output buffer */
+ char *buf_rp; /* Read pointer */
+ char *buf_wp; /* Write pointer */
+ char *buf_end; /* End pointer */
+#ifdef __linux__
+ struct fasync_struct *buf_async;/* Processes waiting for SIGIO */
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ struct sigio *buf_sigio; /* Processes waiting for SIGIO */
+ struct selinfo buf_sel; /* Workspace for select/poll */
+ int buf_selecting;/* True if poll sleeper */
+#endif /* __FreeBSD__ */
+ wait_queue_head_t buf_readers; /* Processes waiting to read */
+ wait_queue_head_t buf_writers; /* Processes waiting to ctx switch */
+
+#ifdef __FreeBSD__
+ /* Sysctl support */
+ struct drm_sysctl_info *sysctl;
+#endif /* __FreeBSD__ */
+
+#if __REALLY_HAVE_AGP
+ drm_agp_head_t *agp;
+#endif
+ struct pci_dev *pdev;
+#ifdef __alpha__
+#if LINUX_VERSION_CODE < 0x020403
+ struct pci_controler *hose;
+#else
+ struct pci_controller *hose;
+#endif
+#endif
+ drm_sg_mem_t *sg; /* Scatter gather memory */
+ unsigned long *ctx_bitmap;
+ void *dev_private;
+ drm_sigdata_t sigdata; /* For block_all_signals */
+ sigset_t sigmask;
+};
+
+extern int DRM(flags);
+extern void DRM(parse_options)( char *s );
+extern int DRM(cpu_valid)( void );
+
+ /* Authentication (drm_auth.h) */
+extern int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv,
+ drm_magic_t magic);
+extern int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic);
+
+ /* Driver support (drm_drv.h) */
+extern int DRM(version)( DRM_OS_IOCTL );
+extern int DRM(write_string)(drm_device_t *dev, const char *s);
+
+ /* Memory management support (drm_memory.h) */
+extern void DRM(mem_init)(void);
+extern void *DRM(alloc)(size_t size, int area);
+extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size,
+ int area);
+extern char *DRM(strdup)(const char *s, int area);
+extern void DRM(strfree)(char *s, int area);
+extern void DRM(free)(void *pt, size_t size, int area);
+extern unsigned long DRM(alloc_pages)(int order, int area);
+extern void DRM(free_pages)(unsigned long address, int order,
+ int area);
+extern void *DRM(ioremap)(unsigned long offset, unsigned long size);
+extern void DRM(ioremapfree)(void *pt, unsigned long size);
+
+#if __REALLY_HAVE_AGP
+extern agp_memory *DRM(alloc_agp)(int pages, u32 type);
+extern int DRM(free_agp)(agp_memory *handle, int pages);
+extern int DRM(bind_agp)(agp_memory *handle, unsigned int start);
+extern int DRM(unbind_agp)(agp_memory *handle);
+#endif
+
+extern int DRM(context_switch)(drm_device_t *dev, int old, int new);
+extern int DRM(context_switch_complete)(drm_device_t *dev, int new);
+
+#if __HAVE_CTX_BITMAP
+extern int DRM(ctxbitmap_init)( drm_device_t *dev );
+extern void DRM(ctxbitmap_cleanup)( drm_device_t *dev );
+extern void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle );
+extern int DRM(ctxbitmap_next)( drm_device_t *dev );
+#endif
+
+ /* Locking IOCTL support (drm_lock.h) */
+extern int DRM(lock_take)(__volatile__ unsigned int *lock,
+ unsigned int context);
+extern int DRM(lock_transfer)(drm_device_t *dev,
+ __volatile__ unsigned int *lock,
+ unsigned int context);
+extern int DRM(lock_free)(drm_device_t *dev,
+ __volatile__ unsigned int *lock,
+ unsigned int context);
+extern int DRM(flush_unblock)(drm_device_t *dev, int context,
+ drm_lock_flags_t flags);
+extern int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
+ drm_lock_flags_t flags);
+extern int DRM(notifier)(void *priv);
+
+ /* Buffer management support (drm_bufs.h) */
+extern int DRM(order)( unsigned long size );
+
+#if __HAVE_DMA
+ /* DMA support (drm_dma.h) */
+extern int DRM(dma_setup)(drm_device_t *dev);
+extern void DRM(dma_takedown)(drm_device_t *dev);
+extern void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
+extern void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid);
+#if __HAVE_OLD_DMA
+/* GH: This is a dirty hack for now...
+ */
+extern void DRM(clear_next_buffer)(drm_device_t *dev);
+extern int DRM(select_queue)(drm_device_t *dev,
+ void (*wrapper)(unsigned long));
+extern int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *dma);
+extern int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma);
+#endif
+#if __HAVE_DMA_IRQ
+extern int DRM(irq_install)( drm_device_t *dev, int irq );
+extern int DRM(irq_uninstall)( drm_device_t *dev );
+extern void DRM(dma_service)( DRM_OS_IRQ_ARGS );
+#if __HAVE_DMA_IRQ_BH
+extern void DRM(dma_immediate_bh)( DRM_OS_TASKQUEUE_ARGS );
+#endif
+#endif
+#if DRM_DMA_HISTOGRAM
+extern int DRM(histogram_slot)(unsigned long count);
+extern void DRM(histogram_compute)(drm_device_t *dev, drm_buf_t *buf);
+#endif
+
+ /* Buffer list support (drm_lists.h) */
+#if __HAVE_DMA_WAITLIST
+extern int DRM(waitlist_create)(drm_waitlist_t *bl, int count);
+extern int DRM(waitlist_destroy)(drm_waitlist_t *bl);
+extern int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf);
+extern drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl);
+#endif
+#if __HAVE_DMA_FREELIST
+extern int DRM(freelist_create)(drm_freelist_t *bl, int count);
+extern int DRM(freelist_destroy)(drm_freelist_t *bl);
+extern int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
+ drm_buf_t *buf);
+extern drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block);
+#endif
+#endif /* __HAVE_DMA */
+
+#if __REALLY_HAVE_AGP
+ /* AGP/GART support (drm_agpsupport.h) */
+extern drm_agp_head_t *DRM(agp_init)(void);
+extern void DRM(agp_uninit)(void);
+extern void DRM(agp_do_release)(void);
+extern agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type);
+extern int DRM(agp_free_memory)(agp_memory *handle);
+extern int DRM(agp_bind_memory)(agp_memory *handle, off_t start);
+extern int DRM(agp_unbind_memory)(agp_memory *handle);
+#endif
+
+ /* Proc support (drm_proc.h) */
+extern struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev,
+ int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry **dev_root);
+extern int DRM(proc_cleanup)(int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry *dev_root);
+
+#if __HAVE_SG
+ /* Scatter Gather Support (drm_scatter.h) */
+extern void DRM(sg_cleanup)(drm_sg_mem_t *entry);
+#endif
+
+#if __REALLY_HAVE_SG
+ /* ATI PCIGART support (ati_pcigart.h) */
+extern int DRM(ati_pcigart_init)(drm_device_t *dev,
+ unsigned long *addr,
+ dma_addr_t *bus_addr);
+extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev,
+ unsigned long addr,
+ dma_addr_t bus_addr);
+#endif
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/sys/dev/drm/drm_agpsupport.h b/sys/dev/drm/drm_agpsupport.h
new file mode 100644
index 0000000..a625c28
--- /dev/null
+++ b/sys/dev/drm/drm_agpsupport.h
@@ -0,0 +1,330 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#include "dev/drm/drmP.h"
+
+#ifdef __FreeBSD__
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#if __REALLY_HAVE_AGP
+#include <sys/agpio.h>
+#endif
+#endif
+
+int DRM(agp_info)(DRM_OS_IOCTL)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ struct agp_info *kern;
+ drm_agp_info_t info;
+
+ 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;
+
+ *(drm_agp_info_t *) data = info;
+ return 0;
+}
+
+int DRM(agp_acquire)(DRM_OS_IOCTL)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ 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)(DRM_OS_IOCTL)
+{
+ drm_device_t *dev = kdev->si_drv1;
+
+ if (!dev->agp || !dev->agp->acquired)
+ return EINVAL;
+ agp_release(dev->agp->agpdev);
+ dev->agp->acquired = 0;
+ return 0;
+
+}
+
+void DRM(agp_do_release)(void)
+{
+ device_t agpdev;
+
+ agpdev = agp_find_device();
+ if (agpdev)
+ agp_release(agpdev);
+}
+
+int DRM(agp_enable)(DRM_OS_IOCTL)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ drm_agp_mode_t mode;
+
+ if (!dev->agp || !dev->agp->acquired) return EINVAL;
+
+ mode = *(drm_agp_mode_t *) data;
+
+ 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_alloc)(DRM_OS_IOCTL)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ 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;
+
+ request = *(drm_agp_buffer_t *) data;
+
+ if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
+ return ENOMEM;
+
+ bzero(entry, sizeof(*entry));
+
+ pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
+ type = (u_int32_t) request.type;
+
+ if (!(handle = DRM(alloc_agp)(pages, type))) {
+ DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ 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;
+
+ *(drm_agp_buffer_t *) data = request;
+
+ return 0;
+}
+
+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_OS_IOCTL)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ drm_agp_binding_t request;
+ drm_agp_mem_t *entry;
+ int retcode;
+
+ if (!dev->agp || !dev->agp->acquired) return EINVAL;
+ request = *(drm_agp_binding_t *) data;
+ if (!(entry = DRM(agp_lookup_entry)(dev, (void *) request.handle)))
+ return EINVAL;
+ if (!entry->bound) return EINVAL;
+ retcode=DRM(unbind_agp)(entry->handle);
+ if (!retcode)
+ {
+ entry->bound=0;
+ return 0;
+ }
+ else
+ return retcode;
+}
+
+int DRM(agp_bind)(DRM_OS_IOCTL)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ drm_agp_binding_t request;
+ drm_agp_mem_t *entry;
+ int retcode;
+ int page;
+
+ DRM_DEBUG("agp_bind, page_size=%x\n", PAGE_SIZE);
+ if (!dev->agp || !dev->agp->acquired)
+ return EINVAL;
+ request = *(drm_agp_binding_t *) data;
+ if (!(entry = DRM(agp_lookup_entry)(dev, (void *) request.handle)))
+ return EINVAL;
+ if (entry->bound) return EINVAL;
+ page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
+ if ((retcode = DRM(bind_agp)(entry->handle, page)))
+ return retcode;
+ entry->bound = dev->agp->base + (page << PAGE_SHIFT);
+ return 0;
+}
+
+int DRM(agp_free)(DRM_OS_IOCTL)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ drm_agp_buffer_t request;
+ drm_agp_mem_t *entry;
+
+ if (!dev->agp || !dev->agp->acquired) return EINVAL;
+ request = *(drm_agp_buffer_t *) data;
+ if (!(entry = DRM(agp_lookup_entry)(dev, (void*) request.handle)))
+ return EINVAL;
+ if (entry->bound) DRM(unbind_agp)(entry->handle);
+
+ if (entry->prev) entry->prev->next = entry->next;
+ else dev->agp->memory = entry->next;
+ if (entry->next) entry->next->prev = entry->prev;
+ DRM(free_agp)(entry->handle, entry->pages);
+ DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ return 0;
+}
+
+drm_agp_head_t *DRM(agp_init)(void)
+{
+ device_t agpdev;
+ drm_agp_head_t *head = NULL;
+ int agp_available = 1;
+
+ agpdev = agp_find_device();
+ if (!agpdev)
+ agp_available = 0;
+
+ DRM_DEBUG("agp_available = %d\n", agp_available);
+
+ if (agp_available) {
+ if (!(head = DRM(alloc)(sizeof(*head), DRM_MEM_AGPLISTS)))
+ return NULL;
+ bzero((void *)head, sizeof(*head));
+ head->agpdev = agpdev;
+ agp_get_info(agpdev, &head->info);
+ head->memory = NULL;
+#if 0 /* bogus */
+ switch (head->agp_info.chipset) {
+ case INTEL_GENERIC: head->chipset = "Intel"; break;
+ case INTEL_LX: head->chipset = "Intel 440LX"; break;
+ case INTEL_BX: head->chipset = "Intel 440BX"; break;
+ case INTEL_GX: head->chipset = "Intel 440GX"; break;
+ case INTEL_I810: head->chipset = "Intel i810"; break;
+ case VIA_GENERIC: head->chipset = "VIA"; break;
+ case VIA_VP3: head->chipset = "VIA VP3"; break;
+ case VIA_MVP3: head->chipset = "VIA MVP3"; break;
+ case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break;
+ case SIS_GENERIC: head->chipset = "SiS"; break;
+ case AMD_GENERIC: head->chipset = "AMD"; break;
+ case AMD_IRONGATE: head->chipset = "AMD Irongate"; break;
+ case ALI_GENERIC: head->chipset = "ALi"; break;
+ case ALI_M1541: head->chipset = "ALi M1541"; break;
+ default:
+ }
+#endif
+ DRM_INFO("AGP at 0x%08x %dMB\n",
+ head->info.ai_aperture_base,
+ head->info.ai_aperture_size >> 20);
+ }
+ return head;
+}
+
+void DRM(agp_uninit)(void)
+{
+/* FIXME: What goes here */
+}
+
+
+agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type)
+{
+ device_t agpdev;
+
+ agpdev = agp_find_device();
+ if (!agpdev)
+ return NULL;
+
+ return agp_alloc_memory(agpdev, type, pages << AGP_PAGE_SHIFT);
+}
+
+int DRM(agp_free_memory)(agp_memory *handle)
+{
+ device_t agpdev;
+
+ agpdev = agp_find_device();
+ if (!agpdev || !handle)
+ return 0;
+
+ agp_free_memory(agpdev, handle);
+ return 1;
+}
+
+int DRM(agp_bind_memory)(agp_memory *handle, off_t start)
+{
+ device_t agpdev;
+
+ agpdev = agp_find_device();
+ if (!agpdev || !handle)
+ return EINVAL;
+
+ return agp_bind_memory(agpdev, handle, start * PAGE_SIZE);
+}
+
+int DRM(agp_unbind_memory)(agp_memory *handle)
+{
+ device_t agpdev;
+
+ agpdev = agp_find_device();
+ if (!agpdev || !handle)
+ return EINVAL;
+
+ return agp_unbind_memory(agpdev, handle);
+}
diff --git a/sys/dev/drm/drm_auth.h b/sys/dev/drm/drm_auth.h
new file mode 100644
index 0000000..2d5baf1
--- /dev/null
+++ b/sys/dev/drm/drm_auth.h
@@ -0,0 +1,177 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/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 = DRM(hash_magic)(magic);
+
+ DRM_OS_LOCK;
+ for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
+ if (pt->magic == magic) {
+ retval = pt->priv;
+ break;
+ }
+ }
+ DRM_OS_UNLOCK;
+ return retval;
+}
+
+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 = (drm_magic_entry_t*) DRM(alloc)(sizeof(*entry), DRM_MEM_MAGIC);
+ if (!entry) DRM_OS_RETURN(ENOMEM);
+ entry->magic = magic;
+ entry->priv = priv;
+ entry->next = NULL;
+
+ DRM_OS_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_OS_UNLOCK;
+
+ return 0;
+}
+
+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_OS_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_OS_UNLOCK;
+#ifdef __FreeBSD__
+ DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC);
+#endif /* __FreeBSD__ */
+ return 0;
+ }
+ }
+ DRM_OS_UNLOCK;
+
+ DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC);
+ DRM_OS_RETURN(EINVAL);
+}
+
+int DRM(getmagic)(DRM_OS_IOCTL)
+{
+ static drm_magic_t sequence = 0;
+ drm_auth_t auth;
+#ifdef __linux__
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ static DRM_OS_SPINTYPE lock;
+ static int first = 1;
+#endif /* __FreeBSD__ */
+ DRM_OS_DEVICE;
+ DRM_OS_PRIV;
+
+#ifdef __FreeBSD__
+ if (first) {
+ DRM_OS_SPININIT(lock, "drm getmagic");
+ first = 0;
+ }
+#endif /* __FreeBSD__ */
+
+ /* Find unique magic */
+ if (priv->magic) {
+ auth.magic = priv->magic;
+ } else {
+ do {
+ DRM_OS_SPINLOCK(&lock);
+ if (!sequence) ++sequence; /* reserve 0 */
+ auth.magic = sequence++;
+ DRM_OS_SPINUNLOCK(&lock);
+ } 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_OS_KRNTOUSR((drm_auth_t *)data, auth, sizeof(auth));
+
+ return 0;
+}
+
+int DRM(authmagic)(DRM_OS_IOCTL)
+{
+ drm_auth_t auth;
+ drm_file_t *file;
+ DRM_OS_DEVICE;
+
+ DRM_OS_KRNFROMUSR(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;
+ }
+ DRM_OS_RETURN(EINVAL);
+}
diff --git a/sys/dev/drm/drm_bufs.h b/sys/dev/drm/drm_bufs.h
new file mode 100644
index 0000000..7d51b46
--- /dev/null
+++ b/sys/dev/drm/drm_bufs.h
@@ -0,0 +1,1284 @@
+/* drm_bufs.h -- Generic buffer template -*- linux-c -*-
+ * Created: Thu Nov 23 03:10:50 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#ifdef __linux__
+#include <linux/vmalloc.h>
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include <machine/param.h>
+#include <sys/mman.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_param.h>
+#endif /* __FreeBSD__ */
+#include "dev/drm/drmP.h"
+
+#ifndef __HAVE_PCI_DMA
+#define __HAVE_PCI_DMA 0
+#endif
+
+#ifndef __HAVE_SG
+#define __HAVE_SG 0
+#endif
+
+#ifndef DRIVER_BUF_PRIV_T
+#define DRIVER_BUF_PRIV_T u32
+#endif
+#ifndef DRIVER_AGP_BUFFERS_MAP
+#if __HAVE_AGP && __HAVE_DMA
+#error "You must define DRIVER_AGP_BUFFERS_MAP()"
+#else
+#define DRIVER_AGP_BUFFERS_MAP( dev ) NULL
+#endif
+#endif
+
+/*
+ * Compute order. Can be made faster.
+ */
+int DRM(order)( unsigned long size )
+{
+ int order;
+ unsigned long tmp;
+
+ for ( order = 0, tmp = size ; tmp >>= 1 ; ++order );
+
+ if ( size & ~(1 << order) )
+ ++order;
+
+ return order;
+}
+
+int DRM(addmap)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_map_t *map;
+#ifdef __linux__
+ drm_map_list_t *list;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_map_list_entry_t *list;
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+ if ( !(filp->f_mode & 3) )
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if (!(dev->flags & (FREAD|FWRITE)))
+#endif /* __FreeBSD__ */
+ DRM_OS_RETURN(EACCES); /* Require read/write */
+
+ map = (drm_map_t *) DRM(alloc)( sizeof(*map), DRM_MEM_MAPS );
+ if ( !map )
+ DRM_OS_RETURN(ENOMEM);
+
+#ifdef __linux__
+ if ( copy_from_user( map, (drm_map_t *)data, sizeof(*map) ) ) {
+ DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+ DRM_OS_RETURN(EFAULT);
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ *map = *(drm_map_t *)data;
+#endif /* __FreeBSD__ */
+
+ /* Only allow shared memory to be removable since we only keep enough
+ * book keeping information about shared memory to allow for removal
+ * when processes fork.
+ */
+ if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) {
+ DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+ map->offset, map->size, map->type );
+#ifdef __linux__
+ if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) {
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if ( (map->offset & PAGE_MASK) || (map->size & PAGE_MASK) ) {
+#endif /* __FreeBSD__ */
+ DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+ DRM_OS_RETURN(EINVAL);
+ }
+ map->mtrr = -1;
+ map->handle = 0;
+
+#ifdef __FreeBSD__
+ TAILQ_FOREACH(list, dev->maplist, link) {
+ drm_map_t *entry = list->map;
+ if ( (entry->offset >= map->offset
+ && (entry->offset) < (map->offset + map->size) )
+ || ((entry->offset + entry->size) >= map->offset
+ && (entry->offset + entry->size) < (map->offset + map->size) )
+ || ((entry->offset < map->offset)
+ && (entry->offset + entry->size) >= (map->offset + map->size) ) )
+ DRM_DEBUG("map collission: add(0x%lx-0x%lx), current(0x%lx-0x%lx)\n",
+ entry->offset, entry->offset + entry->size - 1,
+ map->offset, map->offset + map->size - 1);
+ }
+#endif /* __FreeBSD__ */
+
+ switch ( map->type ) {
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER:
+#if !defined(__sparc__) && !defined(__alpha__)
+ if ( map->offset + map->size < map->offset
+#ifdef __linux__
+ || map->offset < virt_to_phys(high_memory)
+#endif /* __linux__ */
+ ) {
+ DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+ DRM_OS_RETURN(EINVAL);
+ }
+#endif
+#ifdef __alpha__
+ map->offset += dev->hose->mem_space->start;
+#endif
+#if __REALLY_HAVE_MTRR
+ if ( map->type == _DRM_FRAME_BUFFER ||
+ (map->flags & _DRM_WRITE_COMBINING) ) {
+ map->mtrr = mtrr_add( map->offset, map->size,
+ MTRR_TYPE_WRCOMB, 1 );
+ }
+#endif
+ map->handle = DRM(ioremap)( map->offset, map->size );
+ break;
+
+ case _DRM_SHM:
+#ifdef __linux__
+ map->handle = vmalloc_32(map->size);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ map->handle = (void *)DRM(alloc_pages)
+ (DRM(order)(map->size) - PAGE_SHIFT, DRM_MEM_SAREA);
+#endif /* __FreeBSD__ */
+ DRM_DEBUG( "%ld %d %p\n",
+ map->size, DRM(order)( map->size ), map->handle );
+ if ( !map->handle ) {
+ DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ map->offset = (unsigned long)map->handle;
+ if ( map->flags & _DRM_CONTAINS_LOCK ) {
+ dev->lock.hw_lock = map->handle; /* Pointer to lock */
+ }
+ break;
+#if __REALLY_HAVE_AGP
+ case _DRM_AGP:
+#ifdef __alpha__
+ map->offset += dev->hose->mem_space->start;
+#endif
+ map->offset += dev->agp->base;
+ map->mtrr = dev->agp->agp_mtrr; /* for getmap */
+ break;
+#endif
+ case _DRM_SCATTER_GATHER:
+ if (!dev->sg) {
+ DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ DRM_OS_RETURN(EINVAL);
+ }
+ map->offset = map->offset + dev->sg->handle;
+ break;
+
+ default:
+ DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ list = DRM(alloc)(sizeof(*list), DRM_MEM_MAPS);
+ if(!list) {
+ DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ DRM_OS_RETURN(EINVAL);
+ }
+ memset(list, 0, sizeof(*list));
+ list->map = map;
+
+ DRM_OS_LOCK;
+#ifdef __linux__
+ list_add(&list->head, &dev->maplist->head);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TAILQ_INSERT_TAIL(dev->maplist, list, link);
+#endif /* __FreeBSD__ */
+ DRM_OS_UNLOCK;
+
+#ifdef __linux__
+ if ( copy_to_user( (drm_map_t *)data, map, sizeof(*map) ) )
+ DRM_OS_RETURN(EFAULT);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ *(drm_map_t *)data = *map;
+#endif /* __FreeBSD__ */
+
+ if ( map->type != _DRM_SHM ) {
+#ifdef __linux__
+ if ( copy_to_user( &((drm_map_t *)data)->handle,
+ &map->offset,
+ sizeof(map->offset) ) )
+ DRM_OS_RETURN(EFAULT);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ ((drm_map_t *)data)->handle = (void *)map->offset;
+#endif /* __FreeBSD__ */
+ }
+ return 0;
+}
+
+
+/* Remove a map private from list and deallocate resources if the mapping
+ * isn't in use.
+ */
+
+int DRM(rmmap)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+#ifdef __linux__
+ struct list_head *list;
+ drm_map_list_t *r_list = NULL;
+ drm_vma_entry_t *pt, *prev;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_map_list_entry_t *list;
+#endif /* __FreeBSD__ */
+ drm_map_t *map;
+ drm_map_t request;
+ int found_maps = 0;
+
+ DRM_OS_KRNFROMUSR( request, (drm_map_t *)data, sizeof(request) );
+
+ DRM_OS_LOCK;
+#ifdef __linux__
+ list = &dev->maplist->head;
+ list_for_each(list, &dev->maplist->head) {
+ r_list = (drm_map_list_t *) list;
+
+ if(r_list->map &&
+ r_list->map->handle == request.handle &&
+ r_list->map->flags & _DRM_REMOVABLE) break;
+ }
+
+ /* List has wrapped around to the head pointer, or its empty we didn't
+ * find anything.
+ */
+ if(list == (&dev->maplist->head)) {
+ DRM_OS_UNLOCK;
+ DRM_OS_RETURN(EINVAL);
+ }
+ map = r_list->map;
+ list_del(list);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TAILQ_FOREACH(list, dev->maplist, link) {
+ map = list->map;
+ if(map->handle == request.handle &&
+ map->flags & _DRM_REMOVABLE) break;
+ }
+
+ /* List has wrapped around to the head pointer, or its empty we didn't
+ * find anything.
+ */
+ if(list == NULL) {
+ DRM_OS_UNLOCK;
+ DRM_OS_RETURN(EINVAL);
+ }
+ TAILQ_REMOVE(dev->maplist, list, link);
+#endif /* __FreeBSD__ */
+ DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
+
+#ifdef __linux__
+ for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+ if (pt->vma->vm_private_data == map) found_maps++;
+ }
+#endif /* __linux__ */
+
+ if(!found_maps) {
+ switch (map->type) {
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER:
+#if __REALLY_HAVE_MTRR
+ if (map->mtrr >= 0) {
+ int retcode;
+ retcode = mtrr_del(map->mtrr,
+ map->offset,
+ map->size);
+ DRM_DEBUG("mtrr_del = %d\n", retcode);
+ }
+#endif
+ DRM(ioremapfree)(map->handle, map->size);
+ break;
+ case _DRM_SHM:
+#ifdef __linux__
+ vfree(map->handle);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM(free_pages)( (unsigned long)map->handle, DRM(order)(map->size), DRM_MEM_SAREA );
+#endif /* __FreeBSD__ */
+ break;
+ case _DRM_AGP:
+ case _DRM_SCATTER_GATHER:
+ break;
+ }
+ DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ }
+ DRM_OS_UNLOCK;
+ return 0;
+}
+
+#if __HAVE_DMA
+
+
+static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
+{
+ int i;
+
+ if (entry->seg_count) {
+ for (i = 0; i < entry->seg_count; i++) {
+ DRM(free_pages)(entry->seglist[i],
+ entry->page_order,
+ DRM_MEM_DMA);
+ }
+ DRM(free)(entry->seglist,
+ entry->seg_count *
+ sizeof(*entry->seglist),
+ DRM_MEM_SEGS);
+
+ entry->seg_count = 0;
+ }
+
+ if(entry->buf_count) {
+ for(i = 0; i < entry->buf_count; i++) {
+ if(entry->buflist[i].dev_private) {
+ DRM(free)(entry->buflist[i].dev_private,
+ entry->buflist[i].dev_priv_size,
+ DRM_MEM_BUFS);
+ }
+ }
+ DRM(free)(entry->buflist,
+ entry->buf_count *
+ sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+
+#if __HAVE_DMA_FREELIST
+ DRM(freelist_destroy)(&entry->freelist);
+#endif
+
+ entry->buf_count = 0;
+ }
+}
+
+#if __REALLY_HAVE_AGP
+int DRM(addbufs_agp)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ drm_buf_entry_t *entry;
+ drm_buf_t *buf;
+ unsigned long offset;
+ unsigned long agp_offset;
+ int count;
+ int order;
+ int size;
+ int alignment;
+ int page_order;
+ int total;
+ int byte_count;
+ int i;
+ drm_buf_t **temp_buflist;
+
+ if ( !dma ) DRM_OS_RETURN(EINVAL);
+
+ DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) );
+
+ count = request.count;
+ order = DRM(order)( request.size );
+ size = 1 << order;
+
+ alignment = (request.flags & _DRM_PAGE_ALIGN)
+#ifdef __linux__
+ ? PAGE_ALIGN(size) : size;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ ? round_page(size) : size;
+#endif /* __FreeBSD__ */
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = dev->agp->base + request.agp_start;
+
+ DRM_DEBUG( "count: %d\n", count );
+ DRM_DEBUG( "order: %d\n", order );
+ DRM_DEBUG( "size: %d\n", size );
+ DRM_DEBUG( "agp_offset: 0x%lx\n", agp_offset );
+ DRM_DEBUG( "alignment: %d\n", alignment );
+ DRM_DEBUG( "page_order: %d\n", page_order );
+ DRM_DEBUG( "total: %d\n", total );
+
+ if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
+ DRM_OS_RETURN(EINVAL);
+ if ( dev->queue_count )
+ DRM_OS_RETURN(EBUSY); /* Not while in use */
+
+ DRM_OS_SPINLOCK( &dev->count_lock );
+ if ( dev->buf_use ) {
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+ DRM_OS_RETURN(EBUSY);
+ }
+ atomic_inc( &dev->buf_alloc );
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+
+ DRM_OS_LOCK;
+ entry = &dma->bufs[order];
+ if ( entry->buf_count ) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM); /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ if ( !entry->buflist ) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+
+ offset = 0;
+
+ while ( entry->buf_count < count ) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+
+ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+#ifdef __linux__
+ init_waitqueue_head( &buf->dma_wait );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ buf->dma_wait = 0;
+#endif /* __FreeBSD__ */
+ buf->pid = 0;
+
+ buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
+ buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+ DRM_MEM_BUFS );
+ if(!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ DRM(cleanup_buf_error)(entry);
+ }
+ memset( buf->dev_private, 0, buf->dev_priv_size );
+
+#if __HAVE_DMA_HISTOGRAM
+ buf->time_queued = 0;
+ buf->time_dispatched = 0;
+ buf->time_completed = 0;
+ buf->time_freed = 0;
+#endif
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+ DRM_DEBUG( "byte_count: %d\n", byte_count );
+
+ temp_buflist = DRM(realloc)( dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ dma->buflist = temp_buflist;
+
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+ DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+ DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+
+#if __HAVE_DMA_FREELIST
+ DRM(freelist_create)( &entry->freelist, entry->buf_count );
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
+ }
+#endif
+ DRM_OS_UNLOCK;
+
+ request.count = entry->buf_count;
+ request.size = size;
+
+ DRM_OS_KRNTOUSR( (drm_buf_desc_t *)data, request, sizeof(request) );
+
+ dma->flags = _DRM_DMA_USE_AGP;
+
+ atomic_dec( &dev->buf_alloc );
+ return 0;
+}
+#endif /* __REALLY_HAVE_AGP */
+
+#if __HAVE_PCI_DMA
+int DRM(addbufs_pci)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ int count;
+ int order;
+ int size;
+ int total;
+ int page_order;
+ drm_buf_entry_t *entry;
+ unsigned long page;
+ drm_buf_t *buf;
+ int alignment;
+ unsigned long offset;
+ int i;
+ int byte_count;
+ int page_count;
+ unsigned long *temp_pagelist;
+ drm_buf_t **temp_buflist;
+
+ if ( !dma ) DRM_OS_RETURN(EINVAL);
+
+ DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) );
+
+ count = request.count;
+ order = DRM(order)( request.size );
+ size = 1 << order;
+
+ DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n",
+ request.count, request.size, size,
+ order, dev->queue_count );
+
+ if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
+ DRM_OS_RETURN(EINVAL);
+ if ( dev->queue_count )
+ DRM_OS_RETURN(EBUSY); /* Not while in use */
+
+ alignment = (request.flags & _DRM_PAGE_ALIGN)
+#ifdef __linux__
+ ? PAGE_ALIGN(size) : size;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ ? round_page(size) : size;
+#endif /* __FreeBSD__ */
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ DRM_OS_SPINLOCK( &dev->count_lock );
+ if ( dev->buf_use ) {
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+ DRM_OS_RETURN(EBUSY);
+ }
+ atomic_inc( &dev->buf_alloc );
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+
+ DRM_OS_LOCK;
+ entry = &dma->bufs[order];
+ if ( entry->buf_count ) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM); /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ if ( !entry->buflist ) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+ entry->seglist = DRM(alloc)( count * sizeof(*entry->seglist),
+ DRM_MEM_SEGS );
+ if ( !entry->seglist ) {
+ DRM(free)( entry->buflist,
+ count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
+
+ temp_pagelist = DRM(realloc)( dma->pagelist,
+ dma->page_count * sizeof(*dma->pagelist),
+ (dma->page_count + (count << page_order))
+ * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES );
+ if(!temp_pagelist) {
+ DRM(free)( entry->buflist,
+ count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ DRM(free)( entry->seglist,
+ count * sizeof(*entry->seglist),
+ DRM_MEM_SEGS );
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+
+ dma->pagelist = temp_pagelist;
+ DRM_DEBUG( "pagelist: %d entries\n",
+ dma->page_count + (count << page_order) );
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+ byte_count = 0;
+ page_count = 0;
+
+ while ( entry->buf_count < count ) {
+ page = DRM(alloc_pages)( page_order, DRM_MEM_DMA );
+ if ( !page ) break;
+ entry->seglist[entry->seg_count++] = page;
+ for ( i = 0 ; i < (1 << page_order) ; i++ ) {
+ DRM_DEBUG( "page %d @ 0x%08lx\n",
+ dma->page_count + page_count,
+ page + PAGE_SIZE * i );
+ dma->pagelist[dma->page_count + page_count++]
+ = page + PAGE_SIZE * i;
+ }
+ for ( offset = 0 ;
+ offset + size <= total && entry->buf_count < count ;
+ offset += alignment, ++entry->buf_count ) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+ buf->offset = (dma->byte_count + byte_count + offset);
+ buf->address = (void *)(page + offset);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+#ifdef __linux__
+ init_waitqueue_head( &buf->dma_wait );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ buf->dma_wait = 0;
+#endif /* __FreeBSD__ */
+ buf->pid = 0;
+#if __HAVE_DMA_HISTOGRAM
+ buf->time_queued = 0;
+ buf->time_dispatched = 0;
+ buf->time_completed = 0;
+ buf->time_freed = 0;
+#endif
+ DRM_DEBUG( "buffer %d @ %p\n",
+ entry->buf_count, buf->address );
+ }
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+ temp_buflist = DRM(realloc)( dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ dma->buflist = temp_buflist;
+
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += entry->seg_count << page_order;
+ dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
+
+#if __HAVE_DMA_FREELIST
+ DRM(freelist_create)( &entry->freelist, entry->buf_count );
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
+ }
+#endif
+ DRM_OS_UNLOCK;
+
+ request.count = entry->buf_count;
+ request.size = size;
+
+ DRM_OS_KRNTOUSR( (drm_buf_desc_t *)data, request, sizeof(request) );
+
+ atomic_dec( &dev->buf_alloc );
+ return 0;
+
+}
+#endif /* __HAVE_PCI_DMA */
+
+#if __REALLY_HAVE_SG
+int DRM(addbufs_sg)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ drm_buf_entry_t *entry;
+ drm_buf_t *buf;
+ unsigned long offset;
+ unsigned long agp_offset;
+ int count;
+ int order;
+ int size;
+ int alignment;
+ int page_order;
+ int total;
+ int byte_count;
+ int i;
+ drm_buf_t **temp_buflist;
+
+ if ( !dma ) DRM_OS_RETURN(EINVAL);
+
+ DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) );
+
+ count = request.count;
+ order = DRM(order)( request.size );
+ size = 1 << order;
+
+ alignment = (request.flags & _DRM_PAGE_ALIGN)
+#ifdef __linux__
+ ? PAGE_ALIGN(size) : size;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ ? round_page(size) : size;
+#endif /* __FreeBSD__ */
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = request.agp_start;
+
+ DRM_DEBUG( "count: %d\n", count );
+ DRM_DEBUG( "order: %d\n", order );
+ DRM_DEBUG( "size: %d\n", size );
+ DRM_DEBUG( "agp_offset: %ld\n", agp_offset );
+ DRM_DEBUG( "alignment: %d\n", alignment );
+ DRM_DEBUG( "page_order: %d\n", page_order );
+ DRM_DEBUG( "total: %d\n", total );
+
+ if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
+ DRM_OS_RETURN(EINVAL);
+ if ( dev->queue_count ) DRM_OS_RETURN(EBUSY); /* Not while in use */
+
+ DRM_OS_SPINLOCK( &dev->count_lock );
+ if ( dev->buf_use ) {
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+ DRM_OS_RETURN(EBUSY);
+ }
+ atomic_inc( &dev->buf_alloc );
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+
+ DRM_OS_LOCK;
+ entry = &dma->bufs[order];
+ if ( entry->buf_count ) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM); /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ if ( !entry->buflist ) {
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+
+ offset = 0;
+
+ while ( entry->buf_count < count ) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+
+ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset + dev->sg->handle);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+#ifdef __linux__
+ init_waitqueue_head( &buf->dma_wait );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ buf->dma_wait = 0;
+#endif /* __FreeBSD__ */
+ buf->pid = 0;
+
+ buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
+ buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+ DRM_MEM_BUFS );
+ if(!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ DRM(cleanup_buf_error)(entry);
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+
+ memset( buf->dev_private, 0, buf->dev_priv_size );
+
+# if __HAVE_DMA_HISTOGRAM
+ buf->time_queued = 0;
+ buf->time_dispatched = 0;
+ buf->time_completed = 0;
+ buf->time_freed = 0;
+# endif
+ DRM_DEBUG( "buffer %d @ %p\n",
+ entry->buf_count, buf->address );
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+ DRM_DEBUG( "byte_count: %d\n", byte_count );
+
+ temp_buflist = DRM(realloc)( dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ DRM(cleanup_buf_error)(entry);
+ DRM_OS_UNLOCK;
+ atomic_dec( &dev->buf_alloc );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ dma->buflist = temp_buflist;
+
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+ DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+ DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+
+#if __HAVE_DMA_FREELIST
+ DRM(freelist_create)( &entry->freelist, entry->buf_count );
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
+ }
+#endif
+ DRM_OS_UNLOCK;
+
+ request.count = entry->buf_count;
+ request.size = size;
+
+ DRM_OS_KRNTOUSR( (drm_buf_desc_t *)data, request, sizeof(request) );
+
+ dma->flags = _DRM_DMA_USE_SG;
+
+ atomic_dec( &dev->buf_alloc );
+ return 0;
+}
+#endif /* __REALLY_HAVE_SG */
+
+int DRM(addbufs)( DRM_OS_IOCTL )
+{
+ drm_buf_desc_t request;
+
+ DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) );
+
+#if __REALLY_HAVE_AGP
+ if ( request.flags & _DRM_AGP_BUFFER )
+#ifdef __linux__
+ return DRM(addbufs_agp)( inode, filp, cmd, data );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ return DRM(addbufs_agp)( kdev, cmd, data, flags, p );
+#endif /* __FreeBSD__ */
+ else
+#endif
+#if __REALLY_HAVE_SG
+ if ( request.flags & _DRM_SG_BUFFER )
+#ifdef __linux__
+ return DRM(addbufs_sg)( inode, filp, cmd, data );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ return DRM(addbufs_sg)( kdev, cmd, data, flags, p );
+#endif /* __FreeBSD__ */
+ else
+#endif
+#if __HAVE_PCI_DMA
+#ifdef __linux__
+ return DRM(addbufs_pci)( inode, filp, cmd, data );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ return DRM(addbufs_pci)( kdev, cmd, data, flags, p );
+#endif /* __FreeBSD__ */
+#else
+ DRM_OS_RETURN(EINVAL);
+#endif
+}
+
+int DRM(infobufs)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_info_t request;
+ int i;
+ int count;
+
+ if ( !dma ) DRM_OS_RETURN(EINVAL);
+
+ DRM_OS_SPINLOCK( &dev->count_lock );
+ if ( atomic_read( &dev->buf_alloc ) ) {
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+ DRM_OS_RETURN(EBUSY);
+ }
+ ++dev->buf_use; /* Can't allocate more after this call */
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+
+ DRM_OS_KRNFROMUSR( request, (drm_buf_info_t *)data, sizeof(request) );
+
+ for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
+ if ( dma->bufs[i].buf_count ) ++count;
+ }
+
+ DRM_DEBUG( "count = %d\n", count );
+
+ if ( request.count >= count ) {
+ for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
+ if ( dma->bufs[i].buf_count ) {
+ drm_buf_desc_t *to = &request.list[count];
+ drm_buf_entry_t *from = &dma->bufs[i];
+ drm_freelist_t *list = &dma->bufs[i].freelist;
+ if ( DRM_OS_COPYTOUSR( &to->count,
+ &from->buf_count,
+ sizeof(from->buf_count) ) ||
+ DRM_OS_COPYTOUSR( &to->size,
+ &from->buf_size,
+ sizeof(from->buf_size) ) ||
+ DRM_OS_COPYTOUSR( &to->low_mark,
+ &list->low_mark,
+ sizeof(list->low_mark) ) ||
+ DRM_OS_COPYTOUSR( &to->high_mark,
+ &list->high_mark,
+ sizeof(list->high_mark) ) )
+ DRM_OS_RETURN(EFAULT);
+
+ DRM_DEBUG( "%d %d %d %d %d\n",
+ i,
+ dma->bufs[i].buf_count,
+ dma->bufs[i].buf_size,
+ dma->bufs[i].freelist.low_mark,
+ dma->bufs[i].freelist.high_mark );
+ ++count;
+ }
+ }
+ }
+ request.count = count;
+
+ DRM_OS_KRNTOUSR( (drm_buf_info_t *)data, request, sizeof(request) );
+
+ return 0;
+}
+
+int DRM(markbufs)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ int order;
+ drm_buf_entry_t *entry;
+
+ if ( !dma ) DRM_OS_RETURN(EINVAL);
+
+ DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) );
+
+ DRM_DEBUG( "%d, %d, %d\n",
+ request.size, request.low_mark, request.high_mark );
+ order = DRM(order)( request.size );
+ if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER )
+ DRM_OS_RETURN(EINVAL);
+ entry = &dma->bufs[order];
+
+ if ( request.low_mark < 0 || request.low_mark > entry->buf_count )
+ DRM_OS_RETURN(EINVAL);
+ if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
+ DRM_OS_RETURN(EINVAL);
+
+ entry->freelist.low_mark = request.low_mark;
+ entry->freelist.high_mark = request.high_mark;
+
+ return 0;
+}
+
+int DRM(freebufs)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_free_t request;
+ int i;
+ int idx;
+ drm_buf_t *buf;
+
+ if ( !dma ) DRM_OS_RETURN(EINVAL);
+
+ DRM_OS_KRNFROMUSR( request, (drm_buf_free_t *)data, sizeof(request) );
+
+ DRM_DEBUG( "%d\n", request.count );
+ for ( i = 0 ; i < request.count ; i++ ) {
+ if ( DRM_OS_COPYFROMUSR( &idx,
+ &request.list[i],
+ sizeof(idx) ) )
+ DRM_OS_RETURN(EFAULT);
+ if ( idx < 0 || idx >= dma->buf_count ) {
+ DRM_ERROR( "Index %d (of %d max)\n",
+ idx, dma->buf_count - 1 );
+ DRM_OS_RETURN(EINVAL);
+ }
+ buf = dma->buflist[idx];
+ if ( buf->pid != DRM_OS_CURRENTPID ) {
+ DRM_ERROR( "Process %d freeing buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM(free_buffer)( dev, buf );
+ }
+
+ return 0;
+}
+
+int DRM(mapbufs)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ int retcode = 0;
+ const int zero = 0;
+#ifdef __linux__
+ unsigned long virtual, address;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ vm_offset_t virtual, address;
+#if __FreeBSD_version >= 500000
+ struct vmspace *vms = p->td_proc->p_vmspace;
+#else
+ struct vmspace *vms = p->p_vmspace;
+#endif
+#endif /* __FreeBSD__ */
+ drm_buf_map_t request;
+ int i;
+
+ if ( !dma ) DRM_OS_RETURN(EINVAL);
+
+ DRM_OS_SPINLOCK( &dev->count_lock );
+ if ( atomic_read( &dev->buf_alloc ) ) {
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+ DRM_OS_RETURN(EBUSY);
+ }
+ dev->buf_use++; /* Can't allocate more after this call */
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+
+ DRM_OS_KRNFROMUSR( request, (drm_buf_map_t *)data, sizeof(request) );
+
+ if ( request.count >= dma->buf_count ) {
+ if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) ||
+ (__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) {
+ drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
+
+ if ( !map ) {
+ retcode = EINVAL;
+ goto done;
+ }
+
+#ifdef __linux__
+#if LINUX_VERSION_CODE <= 0x020402
+ down( &current->mm->mmap_sem );
+#else
+ down_write( &current->mm->mmap_sem );
+#endif
+
+ virtual = do_mmap( filp, 0, map->size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ (unsigned long)map->offset );
+#if LINUX_VERSION_CODE <= 0x020402
+ up( &current->mm->mmap_sem );
+#else
+ up_write( &current->mm->mmap_sem );
+#endif
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ virtual = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
+ retcode = vm_mmap(&vms->vm_map,
+ &virtual,
+ round_page(map->size),
+ PROT_READ|PROT_WRITE, VM_PROT_ALL,
+ MAP_SHARED,
+ SLIST_FIRST(&kdev->si_hlist),
+ (unsigned long)map->offset );
+#endif /* __FreeBSD__ */
+ } else {
+#ifdef __linux__
+#if LINUX_VERSION_CODE <= 0x020402
+ down( &current->mm->mmap_sem );
+#else
+ down_write( &current->mm->mmap_sem );
+#endif
+
+ virtual = do_mmap( filp, 0, dma->byte_count,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, 0 );
+#if LINUX_VERSION_CODE <= 0x020402
+ up( &current->mm->mmap_sem );
+#else
+ up_write( &current->mm->mmap_sem );
+#endif
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ virtual = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
+ retcode = vm_mmap(&vms->vm_map,
+ &virtual,
+ round_page(dma->byte_count),
+ PROT_READ|PROT_WRITE, VM_PROT_ALL,
+ MAP_SHARED,
+ SLIST_FIRST(&kdev->si_hlist),
+ 0);
+#endif /* __FreeBSD__ */
+ }
+#ifdef __linux__
+ if ( virtual > -1024UL ) {
+ /* Real error */
+ retcode = (signed long)virtual;
+ goto done;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if (retcode)
+ goto done;
+#endif /* __FreeBSD__ */
+ request.virtual = (void *)virtual;
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ if ( DRM_OS_COPYTOUSR( &request.list[i].idx,
+ &dma->buflist[i]->idx,
+ sizeof(request.list[0].idx) ) ) {
+ retcode = EFAULT;
+ goto done;
+ }
+ if ( DRM_OS_COPYTOUSR( &request.list[i].total,
+ &dma->buflist[i]->total,
+ sizeof(request.list[0].total) ) ) {
+ retcode = EFAULT;
+ goto done;
+ }
+ if ( DRM_OS_COPYTOUSR( &request.list[i].used,
+ &zero,
+ sizeof(zero) ) ) {
+ retcode = EFAULT;
+ goto done;
+ }
+ address = virtual + dma->buflist[i]->offset; /* *** */
+ if ( DRM_OS_COPYTOUSR( &request.list[i].address,
+ &address,
+ sizeof(address) ) ) {
+ retcode = EFAULT;
+ goto done;
+ }
+ }
+ }
+ done:
+ request.count = dma->buf_count;
+
+ DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode );
+
+ DRM_OS_KRNTOUSR( (drm_buf_map_t *)data, request, sizeof(request) );
+
+ DRM_OS_RETURN(retcode);
+}
+
+#endif /* __HAVE_DMA */
+
diff --git a/sys/dev/drm/drm_context.h b/sys/dev/drm/drm_context.h
new file mode 100644
index 0000000..dd028ac
--- /dev/null
+++ b/sys/dev/drm/drm_context.h
@@ -0,0 +1,780 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/drmP.h"
+
+#if __HAVE_CTX_BITMAP
+
+/* ================================================================
+ * Context bitmap support
+ */
+
+void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle )
+{
+ if ( ctx_handle < 0 ) goto failed;
+ if ( !dev->ctx_bitmap ) goto failed;
+
+ if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
+ DRM_OS_LOCK;
+ clear_bit( ctx_handle, dev->ctx_bitmap );
+ dev->context_sareas[ctx_handle] = NULL;
+ DRM_OS_UNLOCK;
+ return;
+ }
+failed:
+ DRM_ERROR( "Attempt to free invalid context handle: %d\n",
+ ctx_handle );
+ return;
+}
+
+int DRM(ctxbitmap_next)( drm_device_t *dev )
+{
+ int bit;
+
+ if(!dev->ctx_bitmap) return -1;
+
+ DRM_OS_LOCK;
+ bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
+ if ( bit < DRM_MAX_CTXBITMAP ) {
+ set_bit( bit, dev->ctx_bitmap );
+ DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit );
+ if((bit+1) > dev->max_context) {
+ dev->max_context = (bit+1);
+ if(dev->context_sareas) {
+ drm_map_t **ctx_sareas;
+
+ ctx_sareas = DRM(realloc)(dev->context_sareas,
+ (dev->max_context - 1) *
+ sizeof(*dev->context_sareas),
+ dev->max_context *
+ sizeof(*dev->context_sareas),
+ DRM_MEM_MAPS);
+ if(!ctx_sareas) {
+ clear_bit(bit, dev->ctx_bitmap);
+ DRM_OS_UNLOCK;
+ return -1;
+ }
+ dev->context_sareas = ctx_sareas;
+ dev->context_sareas[bit] = NULL;
+ } else {
+ /* max_context == 1 at this point */
+ dev->context_sareas = DRM(alloc)(
+ dev->max_context *
+ sizeof(*dev->context_sareas),
+ DRM_MEM_MAPS);
+ if(!dev->context_sareas) {
+ clear_bit(bit, dev->ctx_bitmap);
+ DRM_OS_UNLOCK;
+ return -1;
+ }
+ dev->context_sareas[bit] = NULL;
+ }
+ }
+ DRM_OS_UNLOCK;
+ return bit;
+ }
+ DRM_OS_UNLOCK;
+ return -1;
+}
+
+int DRM(ctxbitmap_init)( drm_device_t *dev )
+{
+ int i;
+ int temp;
+
+ DRM_OS_LOCK;
+ dev->ctx_bitmap = (unsigned long *) DRM(alloc)( PAGE_SIZE,
+ DRM_MEM_CTXBITMAP );
+ if ( dev->ctx_bitmap == NULL ) {
+ DRM_OS_UNLOCK;
+ DRM_OS_RETURN(ENOMEM);
+ }
+ memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
+ dev->context_sareas = NULL;
+ dev->max_context = -1;
+ DRM_OS_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_OS_LOCK;
+ if( dev->context_sareas ) DRM(free)( dev->context_sareas,
+ sizeof(*dev->context_sareas) *
+ dev->max_context,
+ DRM_MEM_MAPS );
+ DRM(free)( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
+ DRM_OS_UNLOCK;
+}
+
+/* ================================================================
+ * Per Context SAREA Support
+ */
+
+int DRM(getsareactx)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_priv_map_t request;
+ drm_map_t *map;
+
+ DRM_OS_KRNFROMUSR( request, (drm_ctx_priv_map_t *)data,
+ sizeof(request) );
+
+ DRM_OS_LOCK;
+ if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
+ DRM_OS_UNLOCK;
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ map = dev->context_sareas[request.ctx_id];
+ DRM_OS_UNLOCK;
+
+ request.handle = map->handle;
+
+ DRM_OS_KRNTOUSR( (drm_ctx_priv_map_t *)data, request, sizeof(request) );
+
+ return 0;
+}
+
+int DRM(setsareactx)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_priv_map_t request;
+ drm_map_t *map = NULL;
+#ifdef __linux__
+ drm_map_list_t *r_list = NULL;
+ struct list_head *list;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_map_list_entry_t *list;
+#endif /* __FreeBSD__ */
+
+ DRM_OS_KRNFROMUSR( request, (drm_ctx_priv_map_t *)data,
+ sizeof(request) );
+
+ DRM_OS_LOCK;
+#ifdef __linux__
+ list_for_each(list, &dev->maplist->head) {
+ r_list = (drm_map_list_t *)list;
+ if(r_list->map &&
+ r_list->map->handle == request.handle)
+ goto found;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TAILQ_FOREACH(list, dev->maplist, link) {
+ map=list->map;
+ if(map->handle == request.handle)
+ goto found;
+ }
+#endif /* __FreeBSD__ */
+
+bad:
+ DRM_OS_UNLOCK;
+ return -EINVAL;
+
+found:
+#ifdef __linux__
+ map = r_list->map;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ map = list->map;
+#endif /* __FreeBSD__ */
+ if (!map) goto bad;
+ 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_OS_UNLOCK;
+ return 0;
+}
+
+/* ================================================================
+ * The actual DRM context handling routines
+ */
+
+int DRM(context_switch)( drm_device_t *dev, int old, int new )
+{
+ char buf[64];
+
+ if ( test_and_set_bit( 0, &dev->context_flag ) ) {
+ DRM_ERROR( "Reentering -- FIXME\n" );
+ DRM_OS_RETURN(EBUSY);
+ }
+
+#if __HAVE_DMA_HISTOGRAM
+ dev->ctx_start = get_cycles();
+#endif
+
+ DRM_DEBUG( "Context switch from %d to %d\n", old, new );
+
+ if ( new == dev->last_context ) {
+ clear_bit( 0, &dev->context_flag );
+ return 0;
+ }
+
+ if ( DRM(flags) & DRM_FLAG_NOCTX ) {
+ DRM(context_switch_complete)( dev, new );
+ } else {
+ sprintf( buf, "C %d %d\n", old, new );
+ DRM(write_string)( dev, buf );
+ }
+
+ return 0;
+}
+
+int DRM(context_switch_complete)( drm_device_t *dev, int new )
+{
+ dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
+ dev->last_switch = jiffies;
+
+ 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. */
+#if __HAVE_DMA_HISTOGRAM
+ atomic_inc( &dev->histo.ctx[DRM(histogram_slot)(get_cycles()
+ - dev->ctx_start)] );
+
+#endif
+ clear_bit( 0, &dev->context_flag );
+ DRM_OS_WAKEUP( &dev->context_wait );
+
+ return 0;
+}
+
+int DRM(resctx)( DRM_OS_IOCTL )
+{
+ drm_ctx_res_t res;
+ drm_ctx_t ctx;
+ int i;
+
+ DRM_OS_KRNFROMUSR( res, (drm_ctx_res_t *)data, sizeof(res) );
+
+ if ( res.count >= DRM_RESERVED_CONTEXTS ) {
+ memset( &ctx, 0, sizeof(ctx) );
+ for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
+ ctx.handle = i;
+ if ( DRM_OS_COPYTOUSR( &res.contexts[i],
+ &i, sizeof(i) ) )
+ DRM_OS_RETURN(EFAULT);
+ }
+ }
+ res.count = DRM_RESERVED_CONTEXTS;
+
+ DRM_OS_KRNTOUSR( (drm_ctx_res_t *)data, res, sizeof(res) );
+
+ return 0;
+}
+
+int DRM(addctx)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+
+ DRM_OS_KRNFROMUSR( 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? */
+ DRM_OS_RETURN(ENOMEM);
+ }
+
+ DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) );
+
+ return 0;
+}
+
+int DRM(modctx)( DRM_OS_IOCTL )
+{
+ /* This does nothing */
+ return 0;
+}
+
+int DRM(getctx)( DRM_OS_IOCTL )
+{
+ drm_ctx_t ctx;
+
+ DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+
+ /* This is 0, because we don't handle any context flags */
+ ctx.flags = 0;
+
+ DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) );
+
+ return 0;
+}
+
+int DRM(switchctx)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+
+ DRM_OS_KRNFROMUSR( 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_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+
+ DRM_OS_KRNFROMUSR( 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_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+
+ DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+
+ DRM_DEBUG( "%d\n", ctx.handle );
+#ifdef __linux__
+ if ( ctx.handle == DRM_KERNEL_CONTEXT + 1 ) {
+ priv->remove_auth_on_close = 1;
+ }
+#endif /* __linux__ */
+ if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
+ DRM(ctxbitmap_free)( dev, ctx.handle );
+ }
+
+ return 0;
+}
+
+
+#else /* __HAVE_CTX_BITMAP */
+
+/* ================================================================
+ * Old-style context support
+ */
+
+
+int DRM(context_switch)(drm_device_t *dev, int old, int new)
+{
+ char buf[64];
+ drm_queue_t *q;
+
+#if 0
+ atomic_inc(&dev->total_ctx);
+#endif
+
+ if (test_and_set_bit(0, &dev->context_flag)) {
+ DRM_ERROR("Reentering -- FIXME\n");
+ DRM_OS_RETURN(EBUSY);
+ }
+
+#if __HAVE_DMA_HISTOGRAM
+ dev->ctx_start = get_cycles();
+#endif
+
+ DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+ if (new >= dev->queue_count) {
+ clear_bit(0, &dev->context_flag);
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ if (new == dev->last_context) {
+ clear_bit(0, &dev->context_flag);
+ return 0;
+ }
+
+ q = dev->queuelist[new];
+ atomic_inc(&q->use_count);
+ if (atomic_read(&q->use_count) == 1) {
+ atomic_dec(&q->use_count);
+ clear_bit(0, &dev->context_flag);
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ if (DRM(flags) & DRM_FLAG_NOCTX) {
+ DRM(context_switch_complete)(dev, new);
+ } else {
+ sprintf(buf, "C %d %d\n", old, new);
+ DRM(write_string)(dev, buf);
+ }
+
+ atomic_dec(&q->use_count);
+
+ return 0;
+}
+
+int DRM(context_switch_complete)(drm_device_t *dev, int new)
+{
+ drm_device_dma_t *dma = dev->dma;
+
+ dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
+ dev->last_switch = jiffies;
+
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("Lock isn't held after context switch\n");
+ }
+
+ if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
+ if (DRM(lock_free)(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ DRM_ERROR("Cannot free lock\n");
+ }
+ }
+
+#if __HAVE_DMA_HISTOGRAM
+ atomic_inc(&dev->histo.ctx[DRM(histogram_slot)(get_cycles()
+ - dev->ctx_start)]);
+
+#endif
+ clear_bit(0, &dev->context_flag);
+ DRM_OS_WAKEUP_INT(&dev->context_wait);
+
+ return 0;
+}
+
+static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
+{
+ DRM_DEBUG("\n");
+
+ if (atomic_read(&q->use_count) != 1
+ || atomic_read(&q->finalization)
+ || atomic_read(&q->block_count)) {
+ DRM_ERROR("New queue is already in use: u%ld f%ld b%ld\n",
+ (unsigned long)atomic_read(&q->use_count),
+ (unsigned long)atomic_read(&q->finalization),
+ (unsigned long)atomic_read(&q->block_count));
+ }
+
+ atomic_set(&q->finalization, 0);
+ atomic_set(&q->block_count, 0);
+ atomic_set(&q->block_read, 0);
+ atomic_set(&q->block_write, 0);
+ atomic_set(&q->total_queued, 0);
+ atomic_set(&q->total_flushed, 0);
+ atomic_set(&q->total_locks, 0);
+
+#ifdef __linux__
+ init_waitqueue_head(&q->write_queue);
+ init_waitqueue_head(&q->read_queue);
+ init_waitqueue_head(&q->flush_queue);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ q->write_queue = 0;
+ q->read_queue = 0;
+ q->flush_queue = 0;
+#endif /* __FreeBSD__ */
+
+ q->flags = ctx->flags;
+
+ DRM(waitlist_create)(&q->waitlist, dev->dma->buf_count);
+
+ return 0;
+}
+
+
+/* drm_alloc_queue:
+PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
+ disappear (so all deallocation must be done after IOCTLs are off)
+ 2) dev->queue_count < dev->queue_slots
+ 3) dev->queuelist[i].use_count == 0 and
+ dev->queuelist[i].finalization == 0 if i not in use
+POST: 1) dev->queuelist[i].use_count == 1
+ 2) dev->queue_count < dev->queue_slots */
+
+static int DRM(alloc_queue)(drm_device_t *dev)
+{
+ int i;
+ drm_queue_t *queue;
+ int oldslots;
+ int newslots;
+ /* Check for a free queue */
+ for (i = 0; i < dev->queue_count; i++) {
+ atomic_inc(&dev->queuelist[i]->use_count);
+ if (atomic_read(&dev->queuelist[i]->use_count) == 1
+ && !atomic_read(&dev->queuelist[i]->finalization)) {
+ DRM_DEBUG("%d (free)\n", i);
+ return i;
+ }
+ atomic_dec(&dev->queuelist[i]->use_count);
+ }
+ /* Allocate a new queue */
+ DRM_OS_LOCK;
+
+ queue = gamma_alloc(sizeof(*queue), DRM_MEM_QUEUES);
+ memset(queue, 0, sizeof(*queue));
+ atomic_set(&queue->use_count, 1);
+
+ ++dev->queue_count;
+ if (dev->queue_count >= dev->queue_slots) {
+ oldslots = dev->queue_slots * sizeof(*dev->queuelist);
+ if (!dev->queue_slots) dev->queue_slots = 1;
+ dev->queue_slots *= 2;
+ newslots = dev->queue_slots * sizeof(*dev->queuelist);
+
+ dev->queuelist = DRM(realloc)(dev->queuelist,
+ oldslots,
+ newslots,
+ DRM_MEM_QUEUES);
+ if (!dev->queuelist) {
+ DRM_OS_UNLOCK;
+ DRM_DEBUG("out of memory\n");
+ DRM_OS_RETURN(ENOMEM);
+ }
+ }
+ dev->queuelist[dev->queue_count-1] = queue;
+
+ DRM_OS_UNLOCK;
+ DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
+ return dev->queue_count - 1;
+}
+
+int DRM(resctx)( DRM_OS_IOCTL )
+{
+ drm_ctx_res_t res;
+ drm_ctx_t ctx;
+ int i;
+
+ DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
+
+ DRM_OS_KRNFROMUSR( res, (drm_ctx_res_t *)data, sizeof(res) );
+
+ if (res.count >= DRM_RESERVED_CONTEXTS) {
+ memset(&ctx, 0, sizeof(ctx));
+ for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+ ctx.handle = i;
+ if (DRM_OS_COPYTOUSR(&res.contexts[i],
+ &i,
+ sizeof(i)))
+ DRM_OS_RETURN(EFAULT);
+ }
+ }
+ res.count = DRM_RESERVED_CONTEXTS;
+
+ DRM_OS_KRNTOUSR( (drm_ctx_res_t *)data, res, sizeof(res) );
+
+ return 0;
+}
+
+int DRM(addctx)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+
+ DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+
+ if ((ctx.handle = DRM(alloc_queue)(dev)) == DRM_KERNEL_CONTEXT) {
+ /* Init kernel's context and get a new one. */
+ DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
+ ctx.handle = DRM(alloc_queue)(dev);
+ }
+ DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
+ DRM_DEBUG("%d\n", ctx.handle);
+
+ DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) );
+
+ return 0;
+}
+
+int DRM(modctx)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+ drm_queue_t *q;
+
+ DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+
+ DRM_DEBUG("%d\n", ctx.handle);
+
+ if (ctx.handle < 0 || ctx.handle >= dev->queue_count)
+ DRM_OS_RETURN(EINVAL);
+ q = dev->queuelist[ctx.handle];
+
+ atomic_inc(&q->use_count);
+ if (atomic_read(&q->use_count) == 1) {
+ /* No longer in use */
+ atomic_dec(&q->use_count);
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ if (DRM_BUFCOUNT(&q->waitlist)) {
+ atomic_dec(&q->use_count);
+ DRM_OS_RETURN(EBUSY);
+ }
+
+ q->flags = ctx.flags;
+
+ atomic_dec(&q->use_count);
+ return 0;
+}
+
+int DRM(getctx)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+ drm_queue_t *q;
+
+ DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+
+ DRM_DEBUG("%d\n", ctx.handle);
+
+ if (ctx.handle >= dev->queue_count)
+ DRM_OS_RETURN(EINVAL);
+ q = dev->queuelist[ctx.handle];
+
+ atomic_inc(&q->use_count);
+ if (atomic_read(&q->use_count) == 1) {
+ /* No longer in use */
+ atomic_dec(&q->use_count);
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ ctx.flags = q->flags;
+ atomic_dec(&q->use_count);
+
+ DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) );
+
+ return 0;
+}
+
+int DRM(switchctx)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+
+ DRM_OS_KRNFROMUSR( 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_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+
+ DRM_OS_KRNFROMUSR( 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_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_ctx_t ctx;
+ drm_queue_t *q;
+ drm_buf_t *buf;
+
+ DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+
+ DRM_DEBUG("%d\n", ctx.handle);
+
+ if (ctx.handle >= dev->queue_count) DRM_OS_RETURN(EINVAL);
+ q = dev->queuelist[ctx.handle];
+
+ atomic_inc(&q->use_count);
+ if (atomic_read(&q->use_count) == 1) {
+ /* No longer in use */
+ atomic_dec(&q->use_count);
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ atomic_inc(&q->finalization); /* Mark queue in finalization state */
+ atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
+ finalization) */
+
+ while (test_and_set_bit(0, &dev->interrupt_flag)) {
+#ifdef __linux__
+ schedule();
+ if (signal_pending(current)) {
+ clear_bit(0, &dev->interrupt_flag);
+ DRM_OS_RETURN(EINTR);
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ static int never;
+ int retcode;
+ retcode = tsleep(&never, PZERO|PCATCH, "never", 1);
+ if (retcode)
+ return retcode;
+#endif /* __FreeBSD__ */
+ }
+ /* Remove queued buffers */
+ while ((buf = DRM(waitlist_get)(&q->waitlist))) {
+ DRM(free_buffer)(dev, buf);
+ }
+ clear_bit(0, &dev->interrupt_flag);
+
+ /* Wakeup blocked processes */
+#ifdef __linux__
+ wake_up_interruptible(&q->read_queue);
+ wake_up_interruptible(&q->write_queue);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ wakeup( &q->block_read );
+ wakeup( &q->block_write );
+#endif /* __FreeBSD__ */
+ DRM_OS_WAKEUP_INT( &q->flush_queue );
+ /* Finalization over. Queue is made
+ available when both use_count and
+ finalization become 0, which won't
+ happen until all the waiting processes
+ stop waiting. */
+ atomic_dec(&q->finalization);
+ return 0;
+}
+
+#endif /* __HAVE_CTX_BITMAP */
diff --git a/sys/dev/drm/drm_dma.h b/sys/dev/drm/drm_dma.h
new file mode 100644
index 0000000..73d0efb
--- /dev/null
+++ b/sys/dev/drm/drm_dma.h
@@ -0,0 +1,679 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __FreeBSD__
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+#endif /* __FreeBSD__ */
+#ifdef __linux__
+#define __NO_VERSION__
+#include <linux/interrupt.h> /* For task queue support */
+#endif /* __linux__ */
+
+#include "dev/drm/drmP.h"
+
+#ifndef __HAVE_DMA_WAITQUEUE
+#define __HAVE_DMA_WAITQUEUE 0
+#endif
+#ifndef __HAVE_DMA_RECLAIM
+#define __HAVE_DMA_RECLAIM 0
+#endif
+#ifndef __HAVE_SHARED_IRQ
+#define __HAVE_SHARED_IRQ 0
+#endif
+
+#if __HAVE_SHARED_IRQ
+#define DRM_IRQ_TYPE SA_SHIRQ
+#else
+#define DRM_IRQ_TYPE 0
+#endif
+
+#if __HAVE_DMA
+
+int DRM(dma_setup)( drm_device_t *dev )
+{
+ int i;
+
+ dev->dma = DRM(alloc)( sizeof(*dev->dma), DRM_MEM_DRIVER );
+ if ( !dev->dma )
+ DRM_OS_RETURN(ENOMEM);
+
+ memset( dev->dma, 0, sizeof(*dev->dma) );
+
+ for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
+ memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
+
+ return 0;
+}
+
+void DRM(dma_takedown)(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i, j;
+
+ if (!dma) 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(free_pages)(dma->bufs[i].seglist[j],
+ dma->bufs[i].page_order,
+ DRM_MEM_DMA);
+ }
+ DRM(free)(dma->bufs[i].seglist,
+ dma->bufs[i].seg_count
+ * sizeof(*dma->bufs[0].seglist),
+ DRM_MEM_SEGS);
+ }
+ if(dma->bufs[i].buf_count) {
+ for(j = 0; j < dma->bufs[i].buf_count; j++) {
+ if(dma->bufs[i].buflist[j].dev_private) {
+ DRM(free)(dma->bufs[i].buflist[j].dev_private,
+ dma->bufs[i].buflist[j].dev_priv_size,
+ DRM_MEM_BUFS);
+ }
+ }
+ DRM(free)(dma->bufs[i].buflist,
+ dma->bufs[i].buf_count *
+ sizeof(*dma->bufs[0].buflist),
+ DRM_MEM_BUFS);
+#if __HAVE_DMA_FREELIST
+ DRM(freelist_destroy)(&dma->bufs[i].freelist);
+#endif
+ }
+ }
+
+ if (dma->buflist) {
+ DRM(free)(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ DRM_MEM_BUFS);
+ }
+
+ if (dma->pagelist) {
+ DRM(free)(dma->pagelist,
+ dma->page_count * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES);
+ }
+ DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
+ dev->dma = NULL;
+}
+
+
+#if __HAVE_DMA_HISTOGRAM
+/* This is slow, but is useful for debugging. */
+int DRM(histogram_slot)(unsigned long count)
+{
+ int value = DRM_DMA_HISTOGRAM_INITIAL;
+ int slot;
+
+ for (slot = 0;
+ slot < DRM_DMA_HISTOGRAM_SLOTS;
+ ++slot, value = DRM_DMA_HISTOGRAM_NEXT(value)) {
+ if (count < value) return slot;
+ }
+ return DRM_DMA_HISTOGRAM_SLOTS - 1;
+}
+
+void DRM(histogram_compute)(drm_device_t *dev, drm_buf_t *buf)
+{
+ cycles_t queued_to_dispatched;
+ cycles_t dispatched_to_completed;
+ cycles_t completed_to_freed;
+ int q2d, d2c, c2f, q2c, q2f;
+
+ if (buf->time_queued) {
+ queued_to_dispatched = (buf->time_dispatched
+ - buf->time_queued);
+ dispatched_to_completed = (buf->time_completed
+ - buf->time_dispatched);
+ completed_to_freed = (buf->time_freed
+ - buf->time_completed);
+
+ q2d = DRM(histogram_slot)(queued_to_dispatched);
+ d2c = DRM(histogram_slot)(dispatched_to_completed);
+ c2f = DRM(histogram_slot)(completed_to_freed);
+
+ q2c = DRM(histogram_slot)(queued_to_dispatched
+ + dispatched_to_completed);
+ q2f = DRM(histogram_slot)(queued_to_dispatched
+ + dispatched_to_completed
+ + completed_to_freed);
+
+ atomic_inc(&dev->histo.total);
+ atomic_inc(&dev->histo.queued_to_dispatched[q2d]);
+ atomic_inc(&dev->histo.dispatched_to_completed[d2c]);
+ atomic_inc(&dev->histo.completed_to_freed[c2f]);
+
+ atomic_inc(&dev->histo.queued_to_completed[q2c]);
+ atomic_inc(&dev->histo.queued_to_freed[q2f]);
+
+ }
+ buf->time_queued = 0;
+ buf->time_dispatched = 0;
+ buf->time_completed = 0;
+ buf->time_freed = 0;
+}
+#endif
+
+void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
+{
+ if (!buf) return;
+
+ buf->waiting = 0;
+ buf->pending = 0;
+ buf->pid = 0;
+ buf->used = 0;
+#if __HAVE_DMA_HISTOGRAM
+ buf->time_completed = get_cycles();
+#endif
+
+#ifdef __linux__
+ if ( __HAVE_DMA_WAITQUEUE && waitqueue_active(&buf->dma_wait)) {
+ wake_up_interruptible(&buf->dma_wait);
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if ( buf->dma_wait ) {
+ wakeup( &buf->dma_wait );
+ buf->dma_wait = 0;
+ }
+#endif /* __FreeBSD__ */
+#if __HAVE_DMA_FREELIST
+ else {
+ drm_device_dma_t *dma = dev->dma;
+ /* If processes are waiting, the last one
+ to wake will put the buffer on the free
+ list. If no processes are waiting, we
+ put the buffer on the freelist here. */
+ DRM(freelist_put)(dev, &dma->bufs[buf->order].freelist, buf);
+ }
+#endif
+}
+
+#if !__HAVE_DMA_RECLAIM
+void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid)
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ if (!dma) return;
+ for (i = 0; i < dma->buf_count; i++) {
+ if (dma->buflist[i]->pid == pid) {
+ 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;
+ }
+ }
+ }
+}
+#endif
+
+
+/* GH: This is a big hack for now...
+ */
+#if __HAVE_OLD_DMA
+
+void DRM(clear_next_buffer)(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+
+ dma->next_buffer = NULL;
+ if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
+ DRM_OS_WAKEUP_INT(&dma->next_queue->flush_queue);
+ }
+ dma->next_queue = NULL;
+}
+
+int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
+{
+ int i;
+ int candidate = -1;
+ int j = jiffies;
+
+ if (!dev) {
+ DRM_ERROR("No device\n");
+ return -1;
+ }
+ if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
+ /* This only happens between the time the
+ interrupt is initialized and the time
+ the queues are initialized. */
+ return -1;
+ }
+
+ /* Doing "while locked" DMA? */
+ if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
+ return DRM_KERNEL_CONTEXT;
+ }
+
+ /* If there are buffers on the last_context
+ queue, and we have not been executing
+ this context very long, continue to
+ execute this context. */
+ if (dev->last_switch <= j
+ && dev->last_switch + DRM_TIME_SLICE > j
+ && DRM_WAITCOUNT(dev, dev->last_context)) {
+ return dev->last_context;
+ }
+
+ /* Otherwise, find a candidate */
+ for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
+ if (DRM_WAITCOUNT(dev, i)) {
+ candidate = dev->last_checked = i;
+ break;
+ }
+ }
+
+ if (candidate < 0) {
+ for (i = 0; i < dev->queue_count; i++) {
+ if (DRM_WAITCOUNT(dev, i)) {
+ candidate = dev->last_checked = i;
+ break;
+ }
+ }
+ }
+
+ if (wrapper
+ && candidate >= 0
+ && candidate != dev->last_context
+ && dev->last_switch <= j
+ && dev->last_switch + DRM_TIME_SLICE > j) {
+#ifdef __linux__
+ if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
+ del_timer(&dev->timer);
+ dev->timer.function = wrapper;
+ dev->timer.data = (unsigned long)dev;
+ dev->timer.expires = dev->last_switch+DRM_TIME_SLICE;
+ add_timer(&dev->timer);
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ int s = splclock();
+ if (dev->timer.c_time != dev->last_switch + DRM_TIME_SLICE) {
+ callout_reset(&dev->timer,
+ dev->last_switch + DRM_TIME_SLICE - j,
+ (void (*)(void *))wrapper,
+ dev);
+ }
+ splx(s);
+#endif /* __FreeBSD__ */
+ return -1;
+ }
+
+ return candidate;
+}
+
+
+int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d)
+{
+ int i;
+ drm_queue_t *q;
+ drm_buf_t *buf;
+ int idx;
+ int while_locked = 0;
+ drm_device_dma_t *dma = dev->dma;
+#ifdef __linux__
+ DECLARE_WAITQUEUE(entry, current);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ int error;
+#endif /* __FreeBSD__ */
+
+ DRM_DEBUG("%d\n", d->send_count);
+
+ if (d->flags & _DRM_DMA_WHILE_LOCKED) {
+ int context = dev->lock.hw_lock->lock;
+
+ if (!_DRM_LOCK_IS_HELD(context)) {
+ DRM_ERROR("No lock held during \"while locked\""
+ " request\n");
+ DRM_OS_RETURN(EINVAL);
+ }
+ if (d->context != _DRM_LOCKING_CONTEXT(context)
+ && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
+ DRM_ERROR("Lock held by %d while %d makes"
+ " \"while locked\" request\n",
+ _DRM_LOCKING_CONTEXT(context),
+ d->context);
+ DRM_OS_RETURN(EINVAL);
+ }
+ q = dev->queuelist[DRM_KERNEL_CONTEXT];
+ while_locked = 1;
+ } else {
+ q = dev->queuelist[d->context];
+ }
+
+
+ atomic_inc(&q->use_count);
+ if (atomic_read(&q->block_write)) {
+#ifdef __linux__
+ add_wait_queue(&q->write_queue, &entry);
+ atomic_inc(&q->block_count);
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ if (!atomic_read(&q->block_write)) break;
+ schedule();
+ if (signal_pending(current)) {
+ atomic_dec(&q->use_count);
+ remove_wait_queue(&q->write_queue, &entry);
+ DRM_OS_RETURN(EINTR);
+ }
+ }
+ atomic_dec(&q->block_count);
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&q->write_queue, &entry);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ atomic_inc(&q->block_count);
+ for (;;) {
+ if (!atomic_read(&q->block_write)) break;
+ error = tsleep(&q->block_write, PZERO|PCATCH,
+ "dmawr", 0);
+ if (error) {
+ atomic_dec(&q->use_count);
+ return error;
+ }
+ }
+ atomic_dec(&q->block_count);
+#endif /* __FreeBSD__ */
+ }
+
+ for (i = 0; i < d->send_count; i++) {
+ idx = d->send_indices[i];
+ if (idx < 0 || idx >= dma->buf_count) {
+ atomic_dec(&q->use_count);
+ DRM_ERROR("Index %d (of %d max)\n",
+ d->send_indices[i], dma->buf_count - 1);
+ DRM_OS_RETURN(EINVAL);
+ }
+ buf = dma->buflist[ idx ];
+ if (buf->pid != DRM_OS_CURRENTPID) {
+ atomic_dec(&q->use_count);
+ DRM_ERROR("Process %d using buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid);
+ DRM_OS_RETURN(EINVAL);
+ }
+ if (buf->list != DRM_LIST_NONE) {
+ atomic_dec(&q->use_count);
+ DRM_ERROR("Process %d using buffer %d on list %d\n",
+ DRM_OS_CURRENTPID, buf->idx, buf->list);
+ }
+ buf->used = d->send_sizes[i];
+ buf->while_locked = while_locked;
+ buf->context = d->context;
+ if (!buf->used) {
+ DRM_ERROR("Queueing 0 length buffer\n");
+ }
+ if (buf->pending) {
+ atomic_dec(&q->use_count);
+ DRM_ERROR("Queueing pending buffer:"
+ " buffer %d, offset %d\n",
+ d->send_indices[i], i);
+ DRM_OS_RETURN(EINVAL);
+ }
+ if (buf->waiting) {
+ atomic_dec(&q->use_count);
+ DRM_ERROR("Queueing waiting buffer:"
+ " buffer %d, offset %d\n",
+ d->send_indices[i], i);
+ DRM_OS_RETURN(EINVAL);
+ }
+ buf->waiting = 1;
+ if (atomic_read(&q->use_count) == 1
+ || atomic_read(&q->finalization)) {
+ DRM(free_buffer)(dev, buf);
+ } else {
+ DRM(waitlist_put)(&q->waitlist, buf);
+ atomic_inc(&q->total_queued);
+ }
+ }
+ atomic_dec(&q->use_count);
+
+ return 0;
+}
+
+static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d,
+ int order)
+{
+ int i;
+ drm_buf_t *buf;
+ drm_device_dma_t *dma = dev->dma;
+
+ for (i = d->granted_count; i < d->request_count; i++) {
+ buf = DRM(freelist_get)(&dma->bufs[order].freelist,
+ d->flags & _DRM_DMA_WAIT);
+ if (!buf) break;
+ if (buf->pending || buf->waiting) {
+ DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n",
+ buf->idx,
+ buf->pid,
+ buf->waiting,
+ buf->pending);
+ }
+ buf->pid = DRM_OS_CURRENTPID;
+ if (DRM_OS_COPYTOUSR(&d->request_indices[i],
+ &buf->idx,
+ sizeof(buf->idx)))
+ DRM_OS_RETURN(EFAULT);
+
+ if (DRM_OS_COPYTOUSR(&d->request_sizes[i],
+ &buf->total,
+ sizeof(buf->total)))
+ DRM_OS_RETURN(EFAULT);
+
+ ++d->granted_count;
+ }
+ return 0;
+}
+
+
+int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
+{
+ int order;
+ int retcode = 0;
+ int tmp_order;
+
+ order = DRM(order)(dma->request_size);
+
+ dma->granted_count = 0;
+ retcode = DRM(dma_get_buffers_of_order)(dev, dma, order);
+
+ if (dma->granted_count < dma->request_count
+ && (dma->flags & _DRM_DMA_SMALLER_OK)) {
+ for (tmp_order = order - 1;
+ !retcode
+ && dma->granted_count < dma->request_count
+ && tmp_order >= DRM_MIN_ORDER;
+ --tmp_order) {
+
+ retcode = DRM(dma_get_buffers_of_order)(dev, dma,
+ tmp_order);
+ }
+ }
+
+ if (dma->granted_count < dma->request_count
+ && (dma->flags & _DRM_DMA_LARGER_OK)) {
+ for (tmp_order = order + 1;
+ !retcode
+ && dma->granted_count < dma->request_count
+ && tmp_order <= DRM_MAX_ORDER;
+ ++tmp_order) {
+
+ retcode = DRM(dma_get_buffers_of_order)(dev, dma,
+ tmp_order);
+ }
+ }
+ return 0;
+}
+
+#endif /* __HAVE_OLD_DMA */
+
+
+#if __HAVE_DMA_IRQ
+
+int DRM(irq_install)( drm_device_t *dev, int irq )
+{
+#ifdef __FreeBSD__
+ int rid;
+#endif /* __FreeBSD__ */
+ int retcode;
+
+ if ( !irq )
+ DRM_OS_RETURN(EINVAL);
+
+ DRM_OS_LOCK;
+ if ( dev->irq ) {
+ DRM_OS_UNLOCK;
+ DRM_OS_RETURN(EBUSY);
+ }
+ dev->irq = irq;
+ DRM_OS_UNLOCK;
+
+ DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
+
+ dev->context_flag = 0;
+ dev->interrupt_flag = 0;
+ dev->dma_flag = 0;
+
+ dev->dma->next_buffer = NULL;
+ dev->dma->next_queue = NULL;
+ dev->dma->this_buffer = NULL;
+
+#if __HAVE_DMA_IRQ_BH
+#ifdef __linux__
+ INIT_LIST_HEAD( &dev->tq.list );
+ dev->tq.sync = 0;
+ dev->tq.routine = DRM(dma_immediate_bh);
+ dev->tq.data = dev;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TASK_INIT(&dev->task, 0, DRM(dma_immediate_bh), dev);
+#endif /* __FreeBSD__ */
+#endif
+
+ /* Before installing handler */
+ DRIVER_PREINSTALL();
+
+ /* Install handler */
+#ifdef __linux__
+ retcode = request_irq( dev->irq, DRM(dma_service),
+ DRM_IRQ_TYPE, dev->devname, dev );
+ if ( retcode < 0 ) {
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ rid = 0;
+ dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &rid,
+ 0, ~0, 1, RF_SHAREABLE);
+ if (!dev->irqr)
+ return ENOENT;
+
+ retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY,
+ DRM(dma_service), dev, &dev->irqh);
+ if ( retcode ) {
+#endif /* __FreeBSD__ */
+ DRM_OS_LOCK;
+#ifdef __FreeBSD__
+ bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr);
+#endif /* __FreeBSD__ */
+ dev->irq = 0;
+ DRM_OS_UNLOCK;
+ return retcode;
+ }
+
+ /* After installing handler */
+ DRIVER_POSTINSTALL();
+
+ return 0;
+}
+
+int DRM(irq_uninstall)( drm_device_t *dev )
+{
+ int irq;
+
+ DRM_OS_LOCK;
+ irq = dev->irq;
+ dev->irq = 0;
+ DRM_OS_UNLOCK;
+
+ if ( !irq )
+ DRM_OS_RETURN(EINVAL);
+
+ DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
+
+ DRIVER_UNINSTALL();
+
+#ifdef __linux__
+ free_irq( irq, dev );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
+ bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr);
+#endif /* __FreeBSD__ */
+
+ return 0;
+}
+
+int DRM(control)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_control_t ctl;
+
+ DRM_OS_KRNFROMUSR( ctl, (drm_control_t *) data, sizeof(ctl) );
+
+ switch ( ctl.func ) {
+ case DRM_INST_HANDLER:
+ return DRM(irq_install)( dev, ctl.irq );
+ case DRM_UNINST_HANDLER:
+ return DRM(irq_uninstall)( dev );
+ default:
+ DRM_OS_RETURN(EINVAL);
+ }
+}
+
+#endif /* __HAVE_DMA_IRQ */
+
+#endif /* __HAVE_DMA */
diff --git a/sys/dev/drm/drm_drawable.h b/sys/dev/drm/drm_drawable.h
new file mode 100644
index 0000000..a071128
--- /dev/null
+++ b/sys/dev/drm/drm_drawable.h
@@ -0,0 +1,52 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/drmP.h"
+
+int DRM(adddraw)( DRM_OS_IOCTL )
+{
+ drm_draw_t draw;
+
+ draw.handle = 0; /* NOOP */
+ DRM_DEBUG("%d\n", draw.handle);
+
+ DRM_OS_KRNTOUSR( (drm_draw_t *)data, draw, sizeof(draw) );
+
+ return 0;
+}
+
+int DRM(rmdraw)( DRM_OS_IOCTL )
+{
+ return 0; /* NOOP */
+}
diff --git a/sys/dev/drm/drm_drv.h b/sys/dev/drm/drm_drv.h
new file mode 100644
index 0000000..16fe88d
--- /dev/null
+++ b/sys/dev/drm/drm_drv.h
@@ -0,0 +1,1455 @@
+/* drm_drv.h -- Generic driver template -*- linux-c -*-
+ * Created: Thu Nov 23 03:10:50 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>
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * To use this template, you must at least define the following (samples
+ * given for the MGA driver):
+ *
+ * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
+ *
+ * #define DRIVER_NAME "mga"
+ * #define DRIVER_DESC "Matrox G200/G400"
+ * #define DRIVER_DATE "20001127"
+ *
+ * #define DRIVER_MAJOR 2
+ * #define DRIVER_MINOR 0
+ * #define DRIVER_PATCHLEVEL 2
+ *
+ * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
+ *
+ * #define DRM(x) mga_##x
+ */
+
+#ifndef __MUST_HAVE_AGP
+#define __MUST_HAVE_AGP 0
+#endif
+#ifndef __HAVE_CTX_BITMAP
+#define __HAVE_CTX_BITMAP 0
+#endif
+#ifndef __HAVE_DMA_IRQ
+#define __HAVE_DMA_IRQ 0
+#endif
+#ifndef __HAVE_DMA_QUEUE
+#define __HAVE_DMA_QUEUE 0
+#endif
+#ifndef __HAVE_MULTIPLE_DMA_QUEUES
+#define __HAVE_MULTIPLE_DMA_QUEUES 0
+#endif
+#ifndef __HAVE_DMA_SCHEDULE
+#define __HAVE_DMA_SCHEDULE 0
+#endif
+#ifndef __HAVE_DMA_FLUSH
+#define __HAVE_DMA_FLUSH 0
+#endif
+#ifndef __HAVE_DMA_READY
+#define __HAVE_DMA_READY 0
+#endif
+#ifndef __HAVE_DMA_QUIESCENT
+#define __HAVE_DMA_QUIESCENT 0
+#endif
+#ifndef __HAVE_RELEASE
+#define __HAVE_RELEASE 0
+#endif
+#ifndef __HAVE_COUNTERS
+#define __HAVE_COUNTERS 0
+#endif
+#ifndef __HAVE_SG
+#define __HAVE_SG 0
+#endif
+#ifndef __HAVE_KERNEL_CTX_SWITCH
+#define __HAVE_KERNEL_CTX_SWITCH 0
+#endif
+#ifndef PCI_ANY_ID
+#define PCI_ANY_ID ~0
+#endif
+
+#ifndef DRIVER_PREINIT
+#define DRIVER_PREINIT()
+#endif
+#ifndef DRIVER_POSTINIT
+#define DRIVER_POSTINIT()
+#endif
+#ifndef DRIVER_PRERELEASE
+#define DRIVER_PRERELEASE()
+#endif
+#ifndef DRIVER_PRETAKEDOWN
+#define DRIVER_PRETAKEDOWN()
+#endif
+#ifndef DRIVER_POSTCLEANUP
+#define DRIVER_POSTCLEANUP()
+#endif
+#ifndef DRIVER_PRESETUP
+#define DRIVER_PRESETUP()
+#endif
+#ifndef DRIVER_POSTSETUP
+#define DRIVER_POSTSETUP()
+#endif
+#ifndef DRIVER_IOCTLS
+#define DRIVER_IOCTLS
+#endif
+#ifndef DRIVER_FOPS
+#ifdef __linux__
+#define DRIVER_FOPS \
+static struct file_operations DRM(fops) = { \
+ owner: THIS_MODULE, \
+ open: DRM(open), \
+ flush: DRM(flush), \
+ release: DRM(release), \
+ ioctl: DRM(ioctl), \
+ mmap: DRM(mmap), \
+ read: DRM(read), \
+ fasync: DRM(fasync), \
+ poll: DRM(poll), \
+}
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#if DRM_LINUX
+#include <sys/file.h>
+#include <sys/proc.h>
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include "dev/drm/drm_linux.h"
+#endif
+#endif /* __FreeBSD__ */
+#endif
+
+
+/*
+ * The default number of instances (minor numbers) to initialize.
+ */
+#ifndef DRIVER_NUM_CARDS
+#define DRIVER_NUM_CARDS 1
+#endif
+
+#ifdef __FreeBSD__
+static int DRM(init)(device_t nbdev);
+static void DRM(cleanup)(device_t nbdev);
+
+#define CDEV_MAJOR 145
+#define DRIVER_SOFTC(unit) \
+ ((drm_device_t *) devclass_get_softc(DRM(devclass), unit))
+
+#if __REALLY_HAVE_AGP
+MODULE_DEPEND(DRIVER_NAME, agp, 1, 1, 1);
+#endif
+#if DRM_LINUX
+MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
+#endif
+#endif /* __FreeBSD__ */
+
+static drm_device_t *DRM(device);
+static int *DRM(minor);
+static int DRM(numdevs) = 0;
+
+#ifdef __linux__
+DRIVER_FOPS;
+#endif /* __linux__ */
+
+static drm_ioctl_desc_t DRM(ioctls)[] = {
+ [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_busid), 0, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { DRM(setunique), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { DRM(block), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { DRM(unblock), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { DRM(authmagic), 1, 1 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { DRM(addmap), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { DRM(rmmap), 1, 0 },
+
+#if __HAVE_CTX_BITMAP
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
+#endif
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { DRM(addctx), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { DRM(rmctx), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { DRM(modctx), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { DRM(getctx), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { DRM(switchctx), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { DRM(newctx), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { DRM(resctx), 1, 0 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { DRM(adddraw), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { DRM(rmdraw), 1, 1 },
+
+ [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { DRM(lock), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { DRM(unlock), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { DRM(finish), 1, 0 },
+
+#if __HAVE_DMA
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { DRM(addbufs), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { DRM(markbufs), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { DRM(infobufs), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { DRM(mapbufs), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { DRM(freebufs), 1, 0 },
+
+ /* The DRM_IOCTL_DMA ioctl should be defined by the driver.
+ */
+#if __HAVE_DMA_IRQ
+ [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { DRM(control), 1, 1 },
+#endif
+#endif
+
+#if __REALLY_HAVE_AGP
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { DRM(agp_acquire), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { DRM(agp_release), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { DRM(agp_enable), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { DRM(agp_info), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { DRM(agp_alloc), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { DRM(agp_free), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { DRM(agp_bind), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 },
+#endif
+
+#if __REALLY_HAVE_SG
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
+#endif
+
+ DRIVER_IOCTLS
+};
+
+#define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( DRM(ioctls) )
+
+#ifdef __linux__
+#ifdef MODULE
+static char *drm_opts = NULL;
+#endif
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_PARM( drm_opts, "s" );
+MODULE_LICENSE("GPL and additional rights");
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+static int DRM(probe)(device_t dev)
+{
+ const char *s = 0;
+
+ int pciid=pci_get_devid(dev);
+ int vendor = (pciid & 0x0000ffff);
+ int device = (pciid & 0xffff0000) >> 16;
+ int i=0, done=0;
+ /*DRM_INFO("Checking PCI vendor=%d, device=%d\n", vendor, device);*/
+ while ( !done && (DRM(devicelist)[i].vendor != 0 ) ) {
+ if ( (DRM(devicelist)[i].vendor == vendor) &&
+ (DRM(devicelist)[i].device == device) ) {
+ done=1;
+ if ( DRM(devicelist)[i].supported )
+ s = DRM(devicelist)[i].name;
+ else
+ DRM_INFO("%s not supported\n", DRM(devicelist)[i].name);
+ }
+ i++;
+ }
+
+ if (s) {
+ device_set_desc(dev, s);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int DRM(attach)(device_t dev)
+{
+ return DRM(init)(dev);
+}
+
+static int DRM(detach)(device_t dev)
+{
+ DRM(cleanup)(dev);
+ return 0;
+}
+
+static device_method_t DRM(methods)[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, DRM( probe)),
+ DEVMETHOD(device_attach, DRM( attach)),
+ DEVMETHOD(device_detach, DRM( detach)),
+
+ { 0, 0 }
+};
+
+static driver_t DRM(driver) = {
+ "drm",
+ DRM(methods),
+ sizeof(drm_device_t),
+};
+
+static devclass_t DRM( devclass);
+
+static struct cdevsw DRM( cdevsw) = {
+ /* open */ DRM( open ),
+ /* close */ DRM( close ),
+ /* read */ DRM( read ),
+ /* write */ DRM( write ),
+ /* ioctl */ DRM( ioctl ),
+ /* poll */ DRM( poll ),
+ /* mmap */ DRM( mmap ),
+ /* strategy */ nostrategy,
+ /* name */ DRIVER_NAME,
+ /* maj */ CDEV_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ D_TTY | D_TRACKCLOSE,
+#if __FreeBSD_version >= 500000
+ /* kqfilter */ 0
+#else
+ /* bmaj */ -1
+#endif
+};
+#endif /* __FreeBSD__ */
+
+static int DRM(setup)( drm_device_t *dev )
+{
+ int i;
+
+ DRIVER_PRESETUP();
+ atomic_set( &dev->ioctl_count, 0 );
+ atomic_set( &dev->vma_count, 0 );
+ dev->buf_use = 0;
+ atomic_set( &dev->buf_alloc, 0 );
+
+#if __HAVE_DMA
+ i = DRM(dma_setup)( dev );
+ if ( i < 0 )
+ return i;
+#endif
+
+ dev->counters = 6 + __HAVE_COUNTERS;
+ dev->types[0] = _DRM_STAT_LOCK;
+ dev->types[1] = _DRM_STAT_OPENS;
+ dev->types[2] = _DRM_STAT_CLOSES;
+ dev->types[3] = _DRM_STAT_IOCTLS;
+ dev->types[4] = _DRM_STAT_LOCKS;
+ dev->types[5] = _DRM_STAT_UNLOCKS;
+#ifdef __HAVE_COUNTER6
+ dev->types[6] = __HAVE_COUNTER6;
+#endif
+#ifdef __HAVE_COUNTER7
+ dev->types[7] = __HAVE_COUNTER7;
+#endif
+#ifdef __HAVE_COUNTER8
+ dev->types[8] = __HAVE_COUNTER8;
+#endif
+#ifdef __HAVE_COUNTER9
+ dev->types[9] = __HAVE_COUNTER9;
+#endif
+#ifdef __HAVE_COUNTER10
+ dev->types[10] = __HAVE_COUNTER10;
+#endif
+#ifdef __HAVE_COUNTER11
+ dev->types[11] = __HAVE_COUNTER11;
+#endif
+#ifdef __HAVE_COUNTER12
+ dev->types[12] = __HAVE_COUNTER12;
+#endif
+#ifdef __HAVE_COUNTER13
+ dev->types[13] = __HAVE_COUNTER13;
+#endif
+#ifdef __HAVE_COUNTER14
+ dev->types[14] = __HAVE_COUNTER14;
+#endif
+#ifdef __HAVE_COUNTER15
+ dev->types[14] = __HAVE_COUNTER14;
+#endif
+
+ for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
+ atomic_set( &dev->counts[i], 0 );
+
+ for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
+ dev->magiclist[i].head = NULL;
+ dev->magiclist[i].tail = NULL;
+ }
+
+ dev->maplist = DRM(alloc)(sizeof(*dev->maplist),
+ DRM_MEM_MAPS);
+ if(dev->maplist == NULL) DRM_OS_RETURN(ENOMEM);
+ memset(dev->maplist, 0, sizeof(*dev->maplist));
+#ifdef __linux__
+ INIT_LIST_HEAD(&dev->maplist->head);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TAILQ_INIT(dev->maplist);
+#endif /* __FreeBSD__ */
+ dev->map_count = 0;
+
+ dev->vmalist = NULL;
+ dev->lock.hw_lock = NULL;
+#ifdef __linux__
+ init_waitqueue_head( &dev->lock.lock_queue );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ dev->lock.lock_queue = 0;
+#endif /* __FreeBSD__ */
+ dev->queue_count = 0;
+ dev->queue_reserved = 0;
+ dev->queue_slots = 0;
+ dev->queuelist = NULL;
+ dev->irq = 0;
+ dev->context_flag = 0;
+ dev->interrupt_flag = 0;
+ dev->dma_flag = 0;
+ dev->last_context = 0;
+ dev->last_switch = 0;
+ dev->last_checked = 0;
+#ifdef __linux__
+ init_timer( &dev->timer );
+ init_waitqueue_head( &dev->context_wait );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#if __FreeBSD_version >= 500000
+ callout_init( &dev->timer, 1 );
+#else
+ callout_init( &dev->timer );
+#endif
+ dev->context_wait = 0;
+#endif /* __FreeBSD__ */
+
+ dev->ctx_start = 0;
+ dev->lck_start = 0;
+
+ dev->buf_rp = dev->buf;
+ dev->buf_wp = dev->buf;
+ dev->buf_end = dev->buf + DRM_BSZ;
+#ifdef __linux__
+ dev->buf_async = NULL;
+ init_waitqueue_head( &dev->buf_readers );
+ init_waitqueue_head( &dev->buf_writers );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ dev->buf_sigio = NULL;
+ dev->buf_readers = 0;
+ dev->buf_writers = 0;
+ dev->buf_selecting = 0;
+#endif /* __FreeBSD__ */
+
+ DRM_DEBUG( "\n" );
+
+ /* The kernel's context could be created here, but is now created
+ * in drm_dma_enqueue. This is more resource-efficient for
+ * hardware that does not do DMA, but may mean that
+ * drm_select_queue fails between the time the interrupt is
+ * initialized and the time the queues are initialized.
+ */
+ DRIVER_POSTSETUP();
+ return 0;
+}
+
+
+static int DRM(takedown)( drm_device_t *dev )
+{
+ drm_magic_entry_t *pt, *next;
+ drm_map_t *map;
+#ifdef __linux__
+ drm_map_list_t *r_list;
+ struct list_head *list, *list_next;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_map_list_entry_t *list;
+#endif /* __FreeBSD__ */
+ drm_vma_entry_t *vma, *vma_next;
+ int i;
+
+ DRM_DEBUG( "\n" );
+
+ DRIVER_PRETAKEDOWN();
+#if __HAVE_DMA_IRQ
+ if ( dev->irq ) DRM(irq_uninstall)( dev );
+#endif
+
+ DRM_OS_LOCK;
+#ifdef __linux__
+ del_timer( &dev->timer );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ callout_stop( &dev->timer );
+#endif /* __FreeBSD__ */
+
+ if ( dev->devname ) {
+ DRM(free)( dev->devname, strlen( dev->devname ) + 1,
+ DRM_MEM_DRIVER );
+ dev->devname = NULL;
+ }
+
+ if ( dev->unique ) {
+ DRM(free)( dev->unique, strlen( dev->unique ) + 1,
+ DRM_MEM_DRIVER );
+ dev->unique = NULL;
+ dev->unique_len = 0;
+ }
+ /* Clear pid list */
+ for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
+ for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
+ next = pt->next;
+ DRM(free)( pt, sizeof(*pt), DRM_MEM_MAGIC );
+ }
+ dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
+ }
+
+#if __REALLY_HAVE_AGP
+ /* Clear AGP information */
+ if ( dev->agp ) {
+ drm_agp_mem_t *entry;
+ drm_agp_mem_t *nexte;
+
+ /* Remove AGP resources, but leave dev->agp
+ intact until drv_cleanup is called. */
+ for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
+ nexte = entry->next;
+#ifdef __linux__
+ if ( entry->bound ) DRM(unbind_agp)( entry->memory );
+ DRM(free_agp)( entry->memory, entry->pages );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if ( entry->bound ) DRM(unbind_agp)( entry->handle );
+ DRM(free_agp)( entry->handle, entry->pages );
+#endif /* __FreeBSD__ */
+ DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
+ }
+ dev->agp->memory = NULL;
+
+ if ( dev->agp->acquired ) DRM(agp_do_release)();
+
+ dev->agp->acquired = 0;
+ dev->agp->enabled = 0;
+ }
+#endif
+
+ /* Clear vma list (only built for debugging) */
+ if ( dev->vmalist ) {
+ for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
+ vma_next = vma->next;
+ DRM(free)( vma, sizeof(*vma), DRM_MEM_VMAS );
+ }
+ dev->vmalist = NULL;
+ }
+
+ if( dev->maplist ) {
+#ifdef __linux__
+ for(list = dev->maplist->head.next;
+ list != &dev->maplist->head;
+ list = list_next) {
+ list_next = list->next;
+ r_list = (drm_map_list_t *)list;
+ map = r_list->map;
+ DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+ if(!map) continue;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ while ((list=TAILQ_FIRST(dev->maplist))) {
+ map = list->map;
+#endif /* __FreeBSD__ */
+ switch ( map->type ) {
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER:
+#if __REALLY_HAVE_MTRR
+ if ( map->mtrr >= 0 ) {
+ int retcode;
+ retcode = mtrr_del( map->mtrr,
+ map->offset,
+ map->size );
+ DRM_DEBUG( "mtrr_del=%d\n", retcode );
+ }
+#endif
+ DRM(ioremapfree)( map->handle, map->size );
+ break;
+ case _DRM_SHM:
+#ifdef __linux__
+ vfree(map->handle);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM(free_pages)((unsigned long)map->handle,
+ DRM(order)(map->size)
+ - PAGE_SHIFT,
+ DRM_MEM_SAREA);
+#endif /* __FreeBSD__ */
+ break;
+
+ case _DRM_AGP:
+ /* Do nothing here, because this is all
+ * handled in the AGP/GART driver.
+ */
+ break;
+ case _DRM_SCATTER_GATHER:
+ /* Handle it, but do nothing, if REALLY_HAVE_SG
+ * isn't defined.
+ */
+#if __REALLY_HAVE_SG
+ if(dev->sg) {
+ DRM(sg_cleanup)(dev->sg);
+ dev->sg = NULL;
+ }
+#endif
+ break;
+ }
+#ifdef __FreeBSD__
+ TAILQ_REMOVE(dev->maplist, list, link);
+ DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
+#endif /* __FreeBSD__ */
+ DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ }
+ DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+ dev->maplist = NULL;
+ }
+
+#if __HAVE_DMA_QUEUE || __HAVE_MULTIPLE_DMA_QUEUES
+ if ( dev->queuelist ) {
+ for ( i = 0 ; i < dev->queue_count ; i++ ) {
+ DRM(waitlist_destroy)( &dev->queuelist[i]->waitlist );
+ if ( dev->queuelist[i] ) {
+ DRM(free)( dev->queuelist[i],
+ sizeof(*dev->queuelist[0]),
+ DRM_MEM_QUEUES );
+ dev->queuelist[i] = NULL;
+ }
+ }
+ DRM(free)( dev->queuelist,
+ dev->queue_slots * sizeof(*dev->queuelist),
+ DRM_MEM_QUEUES );
+ dev->queuelist = NULL;
+ }
+ dev->queue_count = 0;
+#endif
+
+#if __HAVE_DMA
+ DRM(dma_takedown)( dev );
+#endif
+ if ( dev->lock.hw_lock ) {
+ dev->lock.hw_lock = NULL; /* SHM removed */
+ dev->lock.pid = 0;
+ DRM_OS_WAKEUP_INT(&dev->lock.lock_queue);
+ }
+ DRM_OS_UNLOCK;
+
+ return 0;
+}
+
+/*
+ * Figure out how many instances to initialize.
+ */
+static int drm_count_cards(void)
+{
+ int num = 0;
+#if defined(DRIVER_CARD_LIST)
+ int i;
+ drm_pci_list_t *l;
+ u16 device, vendor;
+ struct pci_dev *pdev = NULL;
+#endif
+
+ DRM_DEBUG( "\n" );
+
+#if defined(DRIVER_COUNT_CARDS)
+ num = DRIVER_COUNT_CARDS();
+#elif defined(DRIVER_CARD_LIST)
+ for (i = 0, l = DRIVER_CARD_LIST; l[i].vendor != 0; i++) {
+ pdev = NULL;
+ vendor = l[i].vendor;
+ device = l[i].device;
+ if(device == 0xffff) device = PCI_ANY_ID;
+ if(vendor == 0xffff) vendor = PCI_ANY_ID;
+ while ((pdev = pci_find_device(vendor, device, pdev))) {
+ num++; /* FIXME: What about two cards of the same device id? */
+ }
+ }
+#else
+ num = DRIVER_NUM_CARDS;
+#endif
+ DRM_DEBUG("numdevs = %d\n", num);
+ return num;
+}
+
+/* drm_init is called via init_module at module load time, or via
+ * linux/init/main.c (this is not currently supported).
+ */
+#ifdef __linux__
+static int __init drm_init( void )
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+static int DRM(init)( device_t nbdev )
+#endif /* __FreeBSD__ */
+{
+
+ drm_device_t *dev;
+ int i;
+#if __HAVE_CTX_BITMAP
+ int retcode;
+#endif
+ DRM_DEBUG( "\n" );
+
+#ifdef MODULE
+ DRM(parse_options)( drm_opts );
+#endif
+
+ DRM(numdevs) = drm_count_cards();
+ /* Force at least one instance. */
+ if (DRM(numdevs) <= 0)
+ DRM(numdevs) = 1;
+
+ DRM(device) = DRM_OS_MALLOC(sizeof(*DRM(device)) * DRM(numdevs));
+ if (!DRM(device)) {
+ DRM_OS_RETURN(ENOMEM);
+ }
+ DRM(minor) = DRM_OS_MALLOC(sizeof(*(DRM(minor))) * DRM(numdevs));
+ if (!DRM(minor)) {
+ DRM_OS_FREE(DRM(device));
+ DRM_OS_RETURN(ENOMEM);
+ }
+
+ DRIVER_PREINIT();
+
+#ifdef __linux__
+ DRM(mem_init)();
+#endif /* __linux__ */
+
+ for (i = 0; i < DRM(numdevs); i++) {
+#ifdef __linux__
+ dev = &(DRM(device)[i]);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ int unit = device_get_unit(nbdev);
+ /* FIXME??? - multihead !!! */
+ dev = device_get_softc(nbdev);
+#endif /* __FreeBSD__ */
+ memset( (void *)dev, 0, sizeof(*dev) );
+#ifdef __linux__
+ dev->count_lock = SPIN_LOCK_UNLOCKED;
+ sema_init( &dev->struct_sem, 1 );
+ if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
+ return -EPERM;
+ dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
+ dev->name = DRIVER_NAME;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM(minor)[i]=unit;
+ DRM_OS_SPININIT(dev->count_lock, "drm device");
+ lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0);
+ dev->device = nbdev;
+ dev->devnode = make_dev( &DRM(cdevsw),
+ unit,
+ DRM_DEV_UID,
+ DRM_DEV_GID,
+ DRM_DEV_MODE,
+ "dri/card%d", unit );
+ dev->name = DRIVER_NAME;
+ DRM(mem_init)();
+ DRM(sysctl_init)(dev);
+ TAILQ_INIT(&dev->files);
+#endif /* __FreeBSD__ */
+
+#if __REALLY_HAVE_AGP
+ dev->agp = DRM(agp_init)();
+#if __MUST_HAVE_AGP
+ if ( dev->agp == NULL ) {
+ DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+#ifdef __linux__
+ DRM(stub_unregister)(DRM(minor)[i]);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM(sysctl_cleanup)( dev );
+ destroy_dev(dev->devnode);
+#endif /* __FreeBSD__ */
+ DRM(takedown)( dev );
+ DRM_OS_RETURN(ENOMEM);
+ }
+#endif
+#if __REALLY_HAVE_MTRR
+ if (dev->agp)
+ dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+ dev->agp->agp_info.aper_size*1024*1024,
+ MTRR_TYPE_WRCOMB,
+ 1 );
+#endif
+#endif
+
+#if __HAVE_CTX_BITMAP
+ retcode = DRM(ctxbitmap_init)( dev );
+ if( retcode ) {
+ DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
+#ifdef __linux__
+ DRM(stub_unregister)(DRM(minor)[i]);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM(sysctl_cleanup)( dev );
+ destroy_dev(dev->devnode);
+#endif /* __FreeBSD__ */
+ DRM(takedown)( dev );
+ return retcode;
+ }
+#endif
+ DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE,
+ DRM(minor)[i] );
+ }
+
+ DRIVER_POSTINIT();
+
+ return 0;
+}
+
+/* drm_cleanup is called via cleanup_module at module unload time.
+ */
+#ifdef __linux__
+static void __exit drm_cleanup( void )
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+static void DRM(cleanup)(device_t nbdev)
+#endif /* __FreeBSD__ */
+{
+ drm_device_t *dev;
+ int i;
+
+ DRM_DEBUG( "\n" );
+
+ for (i = DRM(numdevs) - 1; i >= 0; i--) {
+#ifdef __linux__
+ dev = &(DRM(device)[i]);
+ if ( DRM(stub_unregister)(DRM(minor)[i]) ) {
+ DRM_ERROR( "Cannot unload module\n" );
+ } else {
+ DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
+ if (i == 0) {
+ DRM_INFO( "Module unloaded\n" );
+ }
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ /* FIXME??? - multihead */
+ dev = device_get_softc(nbdev);
+ DRM(sysctl_cleanup)( dev );
+ destroy_dev(dev->devnode);
+#endif /* __FreeBSD__ */
+#if __HAVE_CTX_BITMAP
+ DRM(ctxbitmap_cleanup)( dev );
+#endif
+
+#if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
+ if ( dev->agp && dev->agp->agp_mtrr >= 0) {
+ int retval;
+ retval = mtrr_del( dev->agp->agp_mtrr,
+ dev->agp->agp_info.aper_base,
+ dev->agp->agp_info.aper_size*1024*1024 );
+ DRM_DEBUG( "mtrr_del=%d\n", retval );
+ }
+#endif
+
+ DRM(takedown)( dev );
+
+#if __REALLY_HAVE_AGP
+ if ( dev->agp ) {
+ DRM(agp_uninit)();
+ DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
+ dev->agp = NULL;
+ }
+#endif
+ }
+ DRIVER_POSTCLEANUP();
+ DRM_OS_FREE(DRM(minor));
+ DRM_OS_FREE(DRM(device));
+ DRM(numdevs) = 0;
+}
+
+#ifdef __linux__
+module_init( drm_init );
+module_exit( drm_cleanup );
+#endif /* __linux__ */
+
+int DRM(version)( DRM_OS_IOCTL )
+{
+ drm_version_t version;
+ int len;
+
+ DRM_OS_KRNFROMUSR( version, (drm_version_t *)data, sizeof(version) );
+
+#define DRM_COPY( name, value ) \
+ len = strlen( value ); \
+ if ( len > name##_len ) len = name##_len; \
+ name##_len = strlen( value ); \
+ if ( len && name ) { \
+ if ( DRM_OS_COPYTOUSR( name, value, len ) ) \
+ DRM_OS_RETURN(EFAULT); \
+ }
+
+ version.version_major = DRIVER_MAJOR;
+ version.version_minor = DRIVER_MINOR;
+ version.version_patchlevel = DRIVER_PATCHLEVEL;
+
+ DRM_COPY( version.name, DRIVER_NAME );
+ DRM_COPY( version.date, DRIVER_DATE );
+ DRM_COPY( version.desc, DRIVER_DESC );
+
+ DRM_OS_KRNTOUSR( (drm_version_t *)data, version, sizeof(version) );
+
+ return 0;
+}
+
+#ifdef __linux__
+int DRM(open)( struct inode *inode, struct file *filp )
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+int DRM( open)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p)
+#endif /* __FreeBSD__ */
+{
+ drm_device_t *dev = NULL;
+ int retcode = 0;
+ int i;
+
+ for (i = 0; i < DRM(numdevs); i++) {
+#ifdef __linux__
+ if (MINOR(inode->i_rdev) == DRM(minor)[i]) {
+ dev = &(DRM(device)[i]);
+ break;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ /* FIXME ??? - multihead */
+ dev = DRIVER_SOFTC(minor(kdev));
+#endif /* __FreeBSD__ */
+ }
+ if (!dev) {
+ DRM_OS_RETURN(ENODEV);
+ }
+
+ DRM_DEBUG( "open_count = %d\n", dev->open_count );
+
+#ifdef __linux__
+ retcode = DRM(open_helper)( inode, filp, dev );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ device_busy(dev->device);
+ retcode = DRM(open_helper)(kdev, flags, fmt, p, dev);
+#endif /* __FreeBSD__ */
+
+ if ( !retcode ) {
+ atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
+ DRM_OS_SPINLOCK( &dev->count_lock );
+ if ( !dev->open_count++ ) {
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+ return DRM(setup)( dev );
+ }
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+ }
+#ifdef __FreeBSD__
+ device_unbusy(dev->device);
+#endif /* __FreeBSD__ */
+
+ return retcode;
+}
+
+#ifdef __linux__
+int DRM(release)( struct inode *inode, struct file *filp )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+int DRM( close)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p)
+{
+ drm_file_t *priv;
+ drm_device_t *dev = kdev->si_drv1;
+#endif /* __FreeBSD__ */
+ int retcode = 0;
+
+#ifdef __linux__
+ lock_kernel();
+ dev = priv->dev;
+#endif /* __linux__ */
+ DRM_DEBUG( "open_count = %d\n", dev->open_count );
+#ifdef __FreeBSD__
+ priv = DRM(find_file_by_proc)(dev, p);
+ if (!priv) {
+ DRM_DEBUG("can't find authenticator\n");
+ return EINVAL;
+ }
+#endif /* __FreeBSD__ */
+
+ DRIVER_PRERELEASE();
+
+ /* ========================================================
+ * Begin inline drm_release
+ */
+
+ DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
+ DRM_OS_CURRENTPID, (long)dev->device, dev->open_count );
+
+ if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
+ && dev->lock.pid == DRM_OS_CURRENTPID) {
+ DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
+ DRM_OS_CURRENTPID,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+#if HAVE_DRIVER_RELEASE
+ DRIVER_RELEASE();
+#endif
+ DRM(lock_free)(dev,
+ &dev->lock.hw_lock->lock,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+
+ /* FIXME: may require heavy-handed reset of
+ hardware at this point, possibly
+ processed via a callback to the X
+ server. */
+ }
+#if __HAVE_RELEASE
+ else if ( dev->lock.hw_lock ) {
+ /* The lock is required to reclaim buffers */
+#ifdef __linux__
+ DECLARE_WAITQUEUE( entry, current );
+ add_wait_queue( &dev->lock.lock_queue, &entry );
+#endif /* __linux__ */
+ for (;;) {
+#ifdef __linux__
+ current->state = TASK_INTERRUPTIBLE;
+#endif /* __linux__ */
+ if ( !dev->lock.hw_lock ) {
+ /* Device has been unregistered */
+ retcode = EINTR;
+ break;
+ }
+ if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT ) ) {
+#ifdef __linux__
+ dev->lock.pid = priv->pid;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ dev->lock.pid = p->p_pid;
+#endif /* __FreeBSD__ */
+ dev->lock.lock_time = jiffies;
+ atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+ break; /* Got lock */
+ }
+ /* Contention */
+#if 0
+ atomic_inc( &dev->total_sleeps );
+#endif
+#ifdef __linux__
+ schedule();
+ if ( signal_pending( current ) ) {
+ retcode = ERESTARTSYS;
+ break;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ retcode = tsleep(&dev->lock.lock_queue,
+ PZERO|PCATCH,
+ "drmlk2",
+ 0);
+ if (retcode)
+ break;
+#endif /* __FreeBSD__ */
+ }
+#ifdef __linux__
+ current->state = TASK_RUNNING;
+ remove_wait_queue( &dev->lock.lock_queue, &entry );
+#endif /* __linux__ */
+ if( !retcode ) {
+ DRIVER_RELEASE();
+ DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT );
+ }
+ }
+#elif __HAVE_DMA
+ DRM(reclaim_buffers)( dev, priv->pid );
+#endif
+
+#ifdef __linux__
+ DRM(fasync)( -1, filp, 0 );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ funsetown(dev->buf_sigio);
+#endif /* __FreeBSD__ */
+
+ DRM_OS_LOCK;
+#ifdef __linux__
+ if ( priv->remove_auth_on_close == 1 ) {
+ drm_file_t *temp = dev->file_first;
+ while ( temp ) {
+ temp->authenticated = 0;
+ temp = temp->next;
+ }
+ }
+ if ( priv->prev ) {
+ priv->prev->next = priv->next;
+ } else {
+ dev->file_first = priv->next;
+ }
+ if ( priv->next ) {
+ priv->next->prev = priv->prev;
+ } else {
+ dev->file_last = priv->prev;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ priv = DRM(find_file_by_proc)(dev, p);
+ if (priv) {
+ priv->refs--;
+ if (!priv->refs) {
+ TAILQ_REMOVE(&dev->files, priv, link);
+ }
+ }
+#endif /* __FreeBSD__ */
+ DRM_OS_UNLOCK;
+
+ DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
+
+ /* ========================================================
+ * End inline drm_release
+ */
+
+ atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
+ DRM_OS_SPINLOCK( &dev->count_lock );
+ if ( !--dev->open_count ) {
+ if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
+ DRM_ERROR( "Device busy: %ld %d\n",
+ (unsigned long)atomic_read( &dev->ioctl_count ),
+ dev->blocked );
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+#ifdef __linux__
+ unlock_kernel();
+#endif /* __linux__ */
+ DRM_OS_RETURN(EBUSY);
+ }
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+#ifdef __linux__
+ unlock_kernel();
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ device_unbusy(dev->device);
+#endif /* __FreeBSD__ */
+ return DRM(takedown)( dev );
+ }
+ DRM_OS_SPINUNLOCK( &dev->count_lock );
+
+#ifdef __linux__
+ unlock_kernel();
+#endif /* __linux__ */
+
+ DRM_OS_RETURN(retcode);
+}
+
+/* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
+ */
+int DRM(ioctl)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ int retcode = 0;
+ drm_ioctl_desc_t *ioctl;
+#ifdef __linux__
+ drm_ioctl_t *func;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ d_ioctl_t *func;
+#endif /* __FreeBSD__ */
+ int nr = DRM_IOCTL_NR(cmd);
+ DRM_OS_PRIV;
+
+ atomic_inc( &dev->ioctl_count );
+ atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
+ ++priv->ioctl_count;
+
+ DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
+ DRM_OS_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated );
+
+#ifdef __FreeBSD__
+ switch (cmd) {
+ case FIONBIO:
+ atomic_dec(&dev->ioctl_count);
+ return 0;
+
+ case FIOASYNC:
+ atomic_dec(&dev->ioctl_count);
+ dev->flags |= FASYNC;
+ return 0;
+
+ case FIOSETOWN:
+ atomic_dec(&dev->ioctl_count);
+ return fsetown(*(int *)data, &dev->buf_sigio);
+
+ case FIOGETOWN:
+ atomic_dec(&dev->ioctl_count);
+ *(int *) data = fgetown(dev->buf_sigio);
+ return 0;
+ }
+#endif /* __FreeBSD__ */
+
+ if ( nr >= DRIVER_IOCTL_COUNT ) {
+ retcode = EINVAL;
+ } else {
+ ioctl = &DRM(ioctls)[nr];
+ func = ioctl->func;
+
+ if ( !func ) {
+ DRM_DEBUG( "no function\n" );
+ retcode = EINVAL;
+ } else if ( ( ioctl->root_only && DRM_OS_CHECKSUSER )
+ || ( ioctl->auth_needed && !priv->authenticated ) ) {
+ retcode = EACCES;
+ } else {
+#ifdef __linux__
+ retcode = func( inode, filp, cmd, data );
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ retcode = func( kdev, cmd, data, flags, p );
+#endif /* __FreeBSD__ */
+ }
+ }
+
+ atomic_dec( &dev->ioctl_count );
+ DRM_OS_RETURN(retcode);
+}
+
+int DRM(lock)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+#ifdef __linux__
+ DECLARE_WAITQUEUE( entry, current );
+#endif /* __linux__ */
+ drm_lock_t lock;
+ int ret = 0;
+#if __HAVE_MULTIPLE_DMA_QUEUES
+ drm_queue_t *q;
+#endif
+#if __HAVE_DMA_HISTOGRAM
+ cycles_t start;
+
+ dev->lck_start = start = get_cycles();
+#endif
+
+ DRM_OS_KRNFROMUSR( lock, (drm_lock_t *)data, sizeof(lock) );
+
+ if ( lock.context == DRM_KERNEL_CONTEXT ) {
+ DRM_ERROR( "Process %d using kernel context %d\n",
+ DRM_OS_CURRENTPID, lock.context );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+ lock.context, DRM_OS_CURRENTPID,
+ dev->lock.hw_lock->lock, lock.flags );
+
+#if __HAVE_DMA_QUEUE
+ if ( lock.context < 0 )
+ DRM_OS_RETURN(EINVAL);
+#elif __HAVE_MULTIPLE_DMA_QUEUES
+ if ( lock.context < 0 || lock.context >= dev->queue_count )
+ DRM_OS_RETURN(EINVAL);
+ q = dev->queuelist[lock.context];
+#endif
+
+#if __HAVE_DMA_FLUSH
+ ret = DRM(flush_block_and_flush)( dev, lock.context, lock.flags );
+#endif
+ if ( !ret ) {
+#ifdef __linux__
+ add_wait_queue( &dev->lock.lock_queue, &entry );
+#endif /* __linux__ */
+ for (;;) {
+#ifdef __linux__
+ current->state = TASK_INTERRUPTIBLE;
+#endif /* __linux__ */
+ if ( !dev->lock.hw_lock ) {
+ /* Device has been unregistered */
+ ret = EINTR;
+ break;
+ }
+ if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
+ lock.context ) ) {
+ dev->lock.pid = DRM_OS_CURRENTPID;
+ dev->lock.lock_time = jiffies;
+ atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+ break; /* Got lock */
+ }
+
+ /* Contention */
+#ifdef __linux__
+ schedule();
+ if ( signal_pending( current ) ) {
+ ret = ERESTARTSYS;
+ break;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ ret = tsleep(&dev->lock.lock_queue,
+ PZERO|PCATCH,
+ "drmlk2",
+ 0);
+ if (ret)
+ break;
+#endif /* __FreeBSD__ */
+ }
+#ifdef __linux__
+ current->state = TASK_RUNNING;
+ remove_wait_queue( &dev->lock.lock_queue, &entry );
+#endif /* __linux__ */
+ }
+
+#if __HAVE_DMA_FLUSH
+ DRM(flush_unblock)( dev, lock.context, lock.flags ); /* cleanup phase */
+#endif
+
+ if ( !ret ) {
+#ifdef __linux__
+ sigemptyset( &dev->sigmask );
+ sigaddset( &dev->sigmask, SIGSTOP );
+ sigaddset( &dev->sigmask, SIGTSTP );
+ sigaddset( &dev->sigmask, SIGTTIN );
+ sigaddset( &dev->sigmask, SIGTTOU );
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals( DRM(notifier),
+ &dev->sigdata, &dev->sigmask );
+#endif /* __linux__ */
+
+#if __HAVE_DMA_READY
+ if ( lock.flags & _DRM_LOCK_READY ) {
+ DRIVER_DMA_READY();
+ }
+#endif
+#if __HAVE_DMA_QUIESCENT
+ if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
+ DRIVER_DMA_QUIESCENT();
+ }
+#endif
+#if __HAVE_KERNEL_CTX_SWITCH
+ if ( dev->last_context != lock.context ) {
+ DRM(context_switch)(dev, dev->last_context,
+ lock.context);
+ }
+#endif
+ }
+
+ DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
+
+#if __HAVE_DMA_HISTOGRAM
+ atomic_inc(&dev->histo.lacq[DRM(histogram_slot)(get_cycles()-start)]);
+#endif
+
+ DRM_OS_RETURN(ret);
+}
+
+
+int DRM(unlock)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_lock_t lock;
+
+ DRM_OS_KRNFROMUSR( lock, (drm_lock_t *)data, sizeof(lock) ) ;
+
+ if ( lock.context == DRM_KERNEL_CONTEXT ) {
+ DRM_ERROR( "Process %d using kernel context %d\n",
+ DRM_OS_CURRENTPID, lock.context );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
+
+#if __HAVE_KERNEL_CTX_SWITCH
+ /* We no longer really hold it, but if we are the next
+ * agent to request it then we should just be able to
+ * take it immediately and not eat the ioctl.
+ */
+ dev->lock.pid = 0;
+ {
+ __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
+ unsigned int old, new, prev, ctx;
+
+ ctx = lock.context;
+ do {
+ old = *plock;
+ new = ctx;
+ prev = cmpxchg(plock, old, new);
+ } while (prev != old);
+ }
+ wake_up_interruptible(&dev->lock.lock_queue);
+#else
+ DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT );
+#if __HAVE_DMA_SCHEDULE
+ DRM(dma_schedule)( dev, 1 );
+#endif
+
+ /* FIXME: Do we ever really need to check this???
+ */
+ if ( 1 /* !dev->context_flag */ ) {
+ if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT ) ) {
+ DRM_ERROR( "\n" );
+ }
+ }
+#endif /* !__HAVE_KERNEL_CTX_SWITCH */
+
+#ifdef __linux__
+ unblock_all_signals();
+#endif /* __linux__ */
+ return 0;
+}
+
+#ifdef __FreeBSD__
+#if DRM_LINUX
+static linux_ioctl_function_t DRM( linux_ioctl);
+static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
+SYSINIT (DRM( register), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler));
+SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler));
+
+/*
+ * Linux emulation IOCTL
+ */
+static int
+DRM(linux_ioctl)(DRM_OS_STRUCTPROC *p, struct linux_ioctl_args* args)
+{
+#if (__FreeBSD_version >= 500000)
+ struct file *fp = p->td_proc->p_fd->fd_ofiles[args->fd];
+#else
+ struct file *fp = p->p_fd->fd_ofiles[args->fd];
+#endif
+ u_long cmd = args->cmd;
+ caddr_t data = (caddr_t) args->arg;
+ /*
+ * Pass the ioctl off to our standard handler.
+ */
+ return(fo_ioctl(fp, cmd, data, p));
+}
+#endif /* DRM_LINUX */
+#endif /* __FreeBSD__ */
diff --git a/sys/dev/drm/drm_fops.h b/sys/dev/drm/drm_fops.h
new file mode 100644
index 0000000..2673629
--- /dev/null
+++ b/sys/dev/drm/drm_fops.h
@@ -0,0 +1,364 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/drmP.h"
+
+#ifdef __linux__
+#include <linux/poll.h>
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+#include <sys/signalvar.h>
+#include <sys/poll.h>
+
+drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_OS_STRUCTPROC *p)
+{
+#if __FreeBSD_version >= 500021
+ uid_t uid = p->td_proc->p_ucred->cr_svuid;
+ pid_t pid = p->td_proc->p_pid;
+#else
+ uid_t uid = p->p_cred->p_svuid;
+ pid_t pid = p->p_pid;
+#endif
+ drm_file_t *priv;
+
+ TAILQ_FOREACH(priv, &dev->files, link)
+ if (priv->pid == pid && priv->uid == uid)
+ return priv;
+ return NULL;
+}
+#endif /* __FreeBSD__ */
+
+/* DRM(open) is called whenever a process opens /dev/drm. */
+
+#ifdef __linux__
+int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
+{
+ kdev_t m = MINOR(inode->i_rdev);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p,
+ drm_device_t *dev)
+{
+ int m = minor(kdev);
+#endif /* __FreeBSD__ */
+ drm_file_t *priv;
+
+#ifdef __linux__
+ if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if (flags & O_EXCL)
+ return EBUSY; /* No exclusive opens */
+ dev->flags = flags;
+#endif /* __FreeBSD__ */
+ if (!DRM(cpu_valid)())
+ DRM_OS_RETURN(EINVAL);
+
+ DRM_DEBUG("pid = %d, minor = %d\n", DRM_OS_CURRENTPID, m);
+
+#ifdef __linux__
+ priv = (drm_file_t *) DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
+ if(!priv) DRM_OS_RETURN(ENOMEM);
+
+ memset(priv, 0, sizeof(*priv));
+ filp->private_data = priv;
+ priv->uid = current->euid;
+ priv->pid = current->pid;
+ priv->minor = m;
+ priv->dev = dev;
+ priv->ioctl_count = 0;
+ priv->authenticated = capable(CAP_SYS_ADMIN);
+
+ down(&dev->struct_sem);
+ if (!dev->file_last) {
+ priv->next = NULL;
+ priv->prev = NULL;
+ dev->file_first = priv;
+ dev->file_last = priv;
+ } else {
+ priv->next = NULL;
+ priv->prev = dev->file_last;
+ dev->file_last->next = priv;
+ dev->file_last = priv;
+ }
+ up(&dev->struct_sem);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ /* FIXME: linux mallocs and bzeros here */
+ priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
+ if (priv) {
+ priv->refs++;
+ } else {
+ priv = (drm_file_t *) DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
+ bzero(priv, sizeof(*priv));
+#if __FreeBSD_version >= 500000
+ priv->uid = p->td_proc->p_ucred->cr_svuid;
+ priv->pid = p->td_proc->p_pid;
+#else
+ priv->uid = p->p_cred->p_svuid;
+ priv->pid = p->p_pid;
+#endif
+
+ priv->refs = 1;
+ priv->minor = m;
+ priv->devXX = dev;
+ priv->ioctl_count = 0;
+ priv->authenticated = !DRM_OS_CHECKSUSER;
+ lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, p);
+ TAILQ_INSERT_TAIL(&dev->files, priv, link);
+ lockmgr(&dev->dev_lock, LK_RELEASE, 0, p);
+ }
+
+ kdev->si_drv1 = dev;
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+#ifdef __alpha__
+ /*
+ * Default the hose
+ */
+ if (!dev->hose) {
+ struct pci_dev *pci_dev;
+ pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
+ if (pci_dev) dev->hose = pci_dev->sysdata;
+ if (!dev->hose) {
+ struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+ if (b) dev->hose = b->sysdata;
+ }
+ }
+#endif
+#endif /* __linux__ */
+
+ return 0;
+}
+
+#ifdef __linux__
+int DRM(flush)(struct file *filp)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+
+ DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
+ current->pid, dev->device, dev->open_count);
+ return 0;
+}
+
+int DRM(fasync)(int fd, struct file *filp, int on)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ int retcode;
+
+ DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
+ retcode = fasync_helper(fd, filp, on, &dev->buf_async);
+ if (retcode < 0) return retcode;
+ return 0;
+}
+#endif /* __linux__ */
+
+/* The drm_read and drm_write_string code (especially that which manages
+ the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
+ DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
+
+#ifdef __linux__
+ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off)
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ssize_t DRM(read)(dev_t kdev, struct uio *uio, int ioflag)
+#endif /* __FreeBSD__ */
+{
+ DRM_OS_DEVICE;
+ int left;
+ int avail;
+ int send;
+ int cur;
+#ifdef __FreeBSD__
+ int error = 0;
+#endif /* __FreeBSD__ */
+
+ DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
+
+ while (dev->buf_rp == dev->buf_wp) {
+ DRM_DEBUG(" sleeping\n");
+#ifdef __linux__
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ interruptible_sleep_on(&dev->buf_readers);
+ if (signal_pending(current)) {
+ DRM_DEBUG(" interrupted\n");
+ return -ERESTARTSYS;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if (dev->flags & FASYNC)
+ return EWOULDBLOCK;
+ error = tsleep(&dev->buf_rp, PZERO|PCATCH, "drmrd", 0);
+ if (error) {
+ DRM_DEBUG(" interrupted\n");
+ return error;
+ }
+#endif /* __FreeBSD__ */
+ DRM_DEBUG(" awake\n");
+ }
+
+ left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
+ avail = DRM_BSZ - left;
+#ifdef __linux__
+ send = DRM_MIN(avail, count);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ send = DRM_MIN(avail, uio->uio_resid);
+#endif /* __FreeBSD__ */
+
+ while (send) {
+ if (dev->buf_wp > dev->buf_rp) {
+ cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
+ } else {
+ cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
+ }
+#ifdef __linux__
+ if (copy_to_user(buf, dev->buf_rp, cur))
+ return -EFAULT;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ error = uiomove(dev->buf_rp, cur, uio);
+ if (error)
+ break;
+#endif /* __FreeBSD__ */
+ dev->buf_rp += cur;
+ if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
+ send -= cur;
+ }
+
+#ifdef __linux__
+ wake_up_interruptible(&dev->buf_writers);
+ return DRM_MIN(avail, count);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ wakeup(&dev->buf_wp);
+ return error;
+#endif /* __FreeBSD__ */
+}
+
+int DRM(write_string)(drm_device_t *dev, const char *s)
+{
+ int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
+ int send = strlen(s);
+ int count;
+
+ DRM_DEBUG("%d left, %d to send (%p, %p)\n",
+ left, send, dev->buf_rp, dev->buf_wp);
+
+ if (left == 1 || dev->buf_wp != dev->buf_rp) {
+ DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
+ left,
+ dev->buf_wp,
+ dev->buf_rp);
+ }
+
+ while (send) {
+ if (dev->buf_wp >= dev->buf_rp) {
+ count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
+ if (count == left) --count; /* Leave a hole */
+ } else {
+ count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
+ }
+ strncpy(dev->buf_wp, s, count);
+ dev->buf_wp += count;
+ if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
+ send -= count;
+ }
+
+#ifdef __linux__
+ if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
+ DRM_DEBUG("waking\n");
+ wake_up_interruptible(&dev->buf_readers);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if (dev->buf_selecting) {
+ dev->buf_selecting = 0;
+ selwakeup(&dev->buf_sel);
+ }
+
+ DRM_DEBUG("dev->buf_sigio=%p\n", dev->buf_sigio);
+ if (dev->buf_sigio) {
+ DRM_DEBUG("dev->buf_sigio->sio_pgid=%d\n", dev->buf_sigio->sio_pgid);
+ pgsigio(dev->buf_sigio, SIGIO, 0);
+ }
+ DRM_DEBUG("waking\n");
+ wakeup(&dev->buf_rp);
+#endif /* __FreeBSD__ */
+
+ return 0;
+}
+
+#ifdef __linux__
+unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
+{
+ DRM_OS_DEVICE;
+
+ poll_wait(filp, &dev->buf_readers, wait);
+ if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
+ return 0;
+}
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+int DRM(poll)(dev_t kdev, int events, DRM_OS_STRUCTPROC *p)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ int s;
+ int revents = 0;
+
+ s = spldrm();
+ if (events & (POLLIN | POLLRDNORM)) {
+ int left = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
+ if (left > 0)
+ revents |= events & (POLLIN | POLLRDNORM);
+ else
+ selrecord(p, &dev->buf_sel);
+ }
+ splx(s);
+
+ return revents;
+}
+
+int DRM(write)(dev_t kdev, struct uio *uio, int ioflag)
+{
+ DRM_DEBUG("pid = %d, device = %p, open_count = %d\n",
+ curproc->p_pid, ((drm_device_t *)kdev->si_drv1)->device, ((drm_device_t *)kdev->si_drv1)->open_count);
+ return 0;
+}
+#endif /* __FreeBSD__ */
diff --git a/sys/dev/drm/drm_init.h b/sys/dev/drm/drm_init.h
new file mode 100644
index 0000000..3839432
--- /dev/null
+++ b/sys/dev/drm/drm_init.h
@@ -0,0 +1,120 @@
+/* drm_init.h -- Setup/Cleanup 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>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/drmP.h"
+
+#if 1 && DRM_DEBUG_CODE
+int DRM(flags) = DRM_FLAG_DEBUG;
+#else
+int DRM(flags) = 0;
+#endif
+
+/* drm_parse_option parses a single option. See description for
+ * drm_parse_options for details.
+ */
+static void DRM(parse_option)(char *s)
+{
+ char *c, *r;
+
+ DRM_DEBUG("\"%s\"\n", s);
+ if (!s || !*s) return;
+ for (c = s; *c && *c != ':'; c++); /* find : or \0 */
+ if (*c) r = c + 1; else r = NULL; /* remember remainder */
+ *c = '\0'; /* terminate */
+ if (!strcmp(s, "noctx")) {
+ DRM(flags) |= DRM_FLAG_NOCTX;
+ DRM_INFO("Server-mediated context switching OFF\n");
+ return;
+ }
+ if (!strcmp(s, "debug")) {
+ DRM(flags) |= DRM_FLAG_DEBUG;
+ DRM_INFO("Debug messages ON\n");
+ return;
+ }
+ DRM_ERROR("\"%s\" is not a valid option\n", s);
+ return;
+}
+
+/* drm_parse_options parse the insmod "drm_opts=" options, or the command-line
+ * options passed to the kernel via LILO. The grammar of the format is as
+ * follows:
+ *
+ * drm ::= 'drm_opts=' option_list
+ * option_list ::= option [ ';' option_list ]
+ * option ::= 'device:' major
+ * | 'debug'
+ * | 'noctx'
+ * major ::= INTEGER
+ *
+ * Note that 's' contains option_list without the 'drm_opts=' part.
+ *
+ * device=major,minor specifies the device number used for /dev/drm
+ * if major == 0 then the misc device is used
+ * if major == 0 and minor == 0 then dynamic misc allocation is used
+ * debug=on specifies that debugging messages will be printk'd
+ * debug=trace specifies that each function call will be logged via printk
+ * debug=off turns off all debugging options
+ *
+ */
+
+void DRM(parse_options)(char *s)
+{
+ char *h, *t, *n;
+
+ DRM_DEBUG("\"%s\"\n", s ?: "");
+ if (!s || !*s) return;
+
+ for (h = t = n = s; h && *h; h = n) {
+ for (; *t && *t != ';'; t++); /* find ; or \0 */
+ if (*t) n = t + 1; else n = NULL; /* remember next */
+ *t = '\0'; /* terminate */
+ DRM(parse_option)(h); /* parse */
+ }
+}
+
+/* drm_cpu_valid returns non-zero if the DRI will run on this CPU, and 0
+ * otherwise.
+ */
+int DRM(cpu_valid)(void)
+{
+#ifdef __linux__
+#if defined(__i386__)
+ if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
+#endif
+#if defined(__sparc__) && !defined(__sparc_v9__)
+ return 0; /* No cmpxchg before v9 sparc. */
+#endif
+#endif /* __linux__ */
+ return 1;
+}
diff --git a/sys/dev/drm/drm_ioctl.h b/sys/dev/drm/drm_ioctl.h
new file mode 100644
index 0000000..24e55e9
--- /dev/null
+++ b/sys/dev/drm/drm_ioctl.h
@@ -0,0 +1,323 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/drmP.h"
+#ifdef __FreeBSD__
+#include <sys/bus.h>
+#include <pci/pcivar.h>
+#endif /* __FreeBSD__ */
+
+int DRM(irq_busid)( DRM_OS_IOCTL )
+{
+ drm_irq_busid_t id;
+#ifdef __linux__
+ struct pci_dev *dev;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ devclass_t pci;
+ device_t bus, dev;
+ device_t *kids;
+ int error, i, num_kids;
+#endif /* __FreeBSD__ */
+
+ DRM_OS_KRNFROMUSR( id, (drm_irq_busid_t *)data, sizeof(id) );
+
+#ifdef __linux__
+ dev = pci_find_slot(id.busnum, PCI_DEVFN(id.devnum, id.funcnum));
+ if (dev) id.irq = dev->irq;
+ else id.irq = 0;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ pci = devclass_find("pci");
+ if (!pci)
+ return ENOENT;
+ bus = devclass_get_device(pci, id.busnum);
+ if (!bus)
+ return ENOENT;
+ error = device_get_children(bus, &kids, &num_kids);
+ if (error)
+ return error;
+
+ dev = 0;
+ for (i = 0; i < num_kids; i++) {
+ dev = kids[i];
+ if (pci_get_slot(dev) == id.devnum
+ && pci_get_function(dev) == id.funcnum)
+ break;
+ }
+
+ free(kids, M_TEMP);
+
+ if (i != num_kids)
+ id.irq = pci_get_irq(dev);
+ else
+ id.irq = 0;
+#endif /* __FreeBSD__ */
+ DRM_DEBUG("%d:%d:%d => IRQ %d\n",
+ id.busnum, id.devnum, id.funcnum, id.irq);
+
+ DRM_OS_KRNTOUSR( (drm_irq_busid_t *)data, id, sizeof(id) );
+
+ return 0;
+}
+
+int DRM(getunique)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_unique_t u;
+
+ DRM_OS_KRNFROMUSR( u, (drm_unique_t *)data, sizeof(u) );
+
+ if (u.unique_len >= dev->unique_len) {
+ if (DRM_OS_COPYTOUSR(u.unique, dev->unique, dev->unique_len))
+ DRM_OS_RETURN(EFAULT);
+ }
+ u.unique_len = dev->unique_len;
+
+ DRM_OS_KRNTOUSR( (drm_unique_t *)data, u, sizeof(u) );
+
+ return 0;
+}
+
+int DRM(setunique)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_unique_t u;
+
+ if (dev->unique_len || dev->unique)
+ DRM_OS_RETURN(EBUSY);
+
+ DRM_OS_KRNFROMUSR( u, (drm_unique_t *)data, sizeof(u) );
+
+ if (!u.unique_len || u.unique_len > 1024)
+ DRM_OS_RETURN(EINVAL);
+
+ dev->unique_len = u.unique_len;
+ dev->unique = DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER);
+
+ if(!dev->unique) DRM_OS_RETURN(ENOMEM);
+
+ if (DRM_OS_COPYFROMUSR(dev->unique, u.unique, dev->unique_len))
+ DRM_OS_RETURN(EFAULT);
+
+ dev->unique[dev->unique_len] = '\0';
+
+ dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
+ DRM_MEM_DRIVER);
+ if(!dev->devname) {
+ DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
+ DRM_OS_RETURN(ENOMEM);
+ }
+ sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
+
+#ifdef __linux__
+ do {
+ struct pci_dev *pci_dev;
+ int b, d, f;
+ char *p;
+
+ for(p = dev->unique; p && *p && *p != ':'; p++);
+ if (!p || !*p) break;
+ b = (int)simple_strtoul(p+1, &p, 10);
+ if (*p != ':') break;
+ d = (int)simple_strtoul(p+1, &p, 10);
+ if (*p != ':') break;
+ f = (int)simple_strtoul(p+1, &p, 10);
+ if (*p) break;
+
+ pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
+ if (pci_dev) {
+ dev->pdev = pci_dev;
+#ifdef __alpha__
+ dev->hose = pci_dev->sysdata;
+#endif
+ }
+ } while(0);
+#endif /* __linux__ */
+
+ return 0;
+}
+
+
+int DRM(getmap)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_map_t map;
+#ifdef __linux__
+ drm_map_list_t *r_list = NULL;
+ struct list_head *list;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_map_t *mapinlist;
+ drm_map_list_entry_t *list;
+#endif /* __FreeBSD__ */
+ int idx;
+ int i = 0;
+
+ DRM_OS_KRNFROMUSR( map, (drm_map_t *)data, sizeof(map) );
+
+ idx = map.offset;
+
+ DRM_OS_LOCK;
+ if (idx < 0 || idx >= dev->map_count) {
+ DRM_OS_UNLOCK;
+ DRM_OS_RETURN(EINVAL);
+ }
+
+#ifdef __linux__
+ list_for_each(list, &dev->maplist->head) {
+ if(i == idx) {
+ r_list = (drm_map_list_t *)list;
+ break;
+ }
+ i++;
+ }
+ if(!r_list || !r_list->map) {
+ DRM_OS_UNLOCK;
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ map.offset = r_list->map->offset;
+ map.size = r_list->map->size;
+ map.type = r_list->map->type;
+ map.flags = r_list->map->flags;
+ map.handle = r_list->map->handle;
+ map.mtrr = r_list->map->mtrr;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TAILQ_FOREACH(list, dev->maplist, link) {
+ mapinlist = list->map;
+ 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++;
+ }
+#endif /* __FreeBSD__ */
+
+ DRM_OS_UNLOCK;
+
+#ifdef __FreeBSD__
+ if (!list)
+ return EINVAL;
+#endif /* __FreeBSD__ */
+
+ DRM_OS_KRNTOUSR( (drm_map_t *)data, map, sizeof(map) );
+
+ return 0;
+}
+
+int DRM(getclient)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_client_t client;
+ drm_file_t *pt;
+ int idx;
+ int i = 0;
+
+ DRM_OS_KRNFROMUSR( client, (drm_client_t *)data, sizeof(client) );
+
+ idx = client.idx;
+ DRM_OS_LOCK;
+#ifdef __linux__
+ for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
+ ;
+
+ if (!pt) {
+ DRM_OS_UNLOCK;
+ DRM_OS_RETURN(EINVAL);
+ }
+ client.auth = pt->authenticated;
+ client.pid = pt->pid;
+ client.uid = pt->uid;
+ client.magic = pt->magic;
+ client.iocs = pt->ioctl_count;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ 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_OS_UNLOCK;
+
+ *(drm_client_t *)data = client;
+ return 0;
+ }
+ i++;
+ }
+#endif /* __FreeBSD__ */
+ DRM_OS_UNLOCK;
+
+ DRM_OS_KRNTOUSR( (drm_client_t *)data, client, sizeof(client) );
+
+ return 0;
+}
+
+int DRM(getstats)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_stats_t stats;
+ int i;
+
+ memset(&stats, 0, sizeof(stats));
+
+ DRM_OS_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_OS_UNLOCK;
+
+ DRM_OS_KRNTOUSR( (drm_stats_t *)data, stats, sizeof(stats) );
+
+ return 0;
+}
diff --git a/sys/dev/drm/drm_linux.h b/sys/dev/drm/drm_linux.h
new file mode 100644
index 0000000..2f712cf
--- /dev/null
+++ b/sys/dev/drm/drm_linux.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2000 by Coleman Kane <cokane@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Gardner Buchanan.
+ * 4. The name of Gardner Buchanan may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* FIXME: There are IOCTLS to merge in here, see drm.h*/
+
+/* Query IOCTLs */
+/* XFree86 4.1.x DRI support */
+
+#define LINUX_DRM_IOCTL_VERSION 0x6400
+#define LINUX_DRM_IOCTL_GET_UNIQUE 0x6401
+#define LINUX_DRM_IOCTL_GET_MAGIC 0x6402
+#define LINUX_DRM_IOCTL_IRQ_BUSID 0x6403
+#define LINUX_DRM_IOCTL_GET_MAP 0x6404
+#define LINUX_DRM_IOCTL_GET_CLIENT 0x6405
+#define LINUX_DRM_IOCTL_GET_STATS 0x6406
+
+#define LINUX_DRM_IOCTL_SET_UNIQUE 0x6410
+#define LINUX_DRM_IOCTL_AUTH_MAGIC 0x6411
+#define LINUX_DRM_IOCTL_BLOCK 0x6412
+#define LINUX_DRM_IOCTL_UNBLOCK 0x6413
+#define LINUX_DRM_IOCTL_CONTROL 0x6414
+#define LINUX_DRM_IOCTL_ADD_MAP 0x6415
+#define LINUX_DRM_IOCTL_ADD_BUFS 0x6416
+#define LINUX_DRM_IOCTL_MARK_BUFS 0x6417
+#define LINUX_DRM_IOCTL_INFO_BUFS 0x6418
+#define LINUX_DRM_IOCTL_MAP_BUFS 0x6419
+#define LINUX_DRM_IOCTL_FREE_BUFS 0x641a
+
+#define LINUX_DRM_IOCTL_RM_MAP 0x641b
+
+#define LINUX_DRM_IOCTL_SET_SAREA_CTX 0x641c
+#define LINUX_DRM_IOCTL_GET_SAREA_CTX 0x641d
+
+#define LINUX_DRM_IOCTL_ADD_CTX 0x6420
+#define LINUX_DRM_IOCTL_RM_CTX 0x6421
+#define LINUX_DRM_IOCTL_MOD_CTX 0x6422
+#define LINUX_DRM_IOCTL_GET_CTX 0x6423
+#define LINUX_DRM_IOCTL_SWITCH_CTX 0x6424
+#define LINUX_DRM_IOCTL_NEW_CTX 0x6425
+#define LINUX_DRM_IOCTL_RES_CTX 0x6426
+#define LINUX_DRM_IOCTL_ADD_DRAW 0x6427
+#define LINUX_DRM_IOCTL_RM_DRAW 0x6428
+#define LINUX_DRM_IOCTL_DMA 0x6429
+#define LINUX_DRM_IOCTL_LOCK 0x642a
+#define LINUX_DRM_IOCTL_UNLOCK 0x642b
+#define LINUX_DRM_IOCTL_FINISH 0x642c
+
+#define LINUX_DRM_IOCTL_AGP_ACQUIRE 0x6430
+#define LINUX_DRM_IOCTL_AGP_RELEASE 0x6431
+#define LINUX_DRM_IOCTL_AGP_ENABLE 0x6432
+#define LINUX_DRM_IOCTL_AGP_INFO 0x6433
+#define LINUX_DRM_IOCTL_AGP_ALLOC 0x6434
+#define LINUX_DRM_IOCTL_AGP_FREE 0x6435
+#define LINUX_DRM_IOCTL_AGP_BIND 0x6436
+#define LINUX_DRM_IOCTL_AGP_UNBIND 0x6437
+
+#define LINUX_DRM_IOCTL_SG_ALLOC 0x6438
+#define LINUX_DRM_IOCTL_SG_FREE 0x6439
+
+/* MGA specific ioctls */
+#define LINUX_DRM_IOCTL_MGA_INIT 0x6440
+#define LINUX_DRM_IOCTL_MGA_FLUSH 0x6441
+#define LINUX_DRM_IOCTL_MGA_RESET 0x6442
+#define LINUX_DRM_IOCTL_MGA_SWAP 0x6443
+#define LINUX_DRM_IOCTL_MGA_CLEAR 0x6444
+#define LINUX_DRM_IOCTL_MGA_VERTEX 0x6445
+#define LINUX_DRM_IOCTL_MGA_INDICES 0x6446
+#define LINUX_DRM_IOCTL_MGA_ILOAD 0x6447
+#define LINUX_DRM_IOCTL_MGA_BLIT 0x6448
+
+/* i810 specific ioctls */
+#define LINUX_DRM_IOCTL_I810_INIT 0x6440
+#define LINUX_DRM_IOCTL_I810_VERTEX 0x6441
+#define LINUX_DRM_IOCTL_I810_CLEAR 0x6442
+#define LINUX_DRM_IOCTL_I810_FLUSH 0x6443
+#define LINUX_DRM_IOCTL_I810_GETAGE 0x6444
+#define LINUX_DRM_IOCTL_I810_GETBUF 0x6445
+#define LINUX_DRM_IOCTL_I810_SWAP 0x6446
+#define LINUX_DRM_IOCTL_I810_COPY 0x6447
+#define LINUX_DRM_IOCTL_I810_DOCOPY 0x6448
+
+/* Rage 128 specific ioctls */
+#define LINUX_DRM_IOCTL_R128_INIT 0x6440
+#define LINUX_DRM_IOCTL_R128_CCE_START 0x6441
+#define LINUX_DRM_IOCTL_R128_CCE_STOP 0x6442
+#define LINUX_DRM_IOCTL_R128_CCE_RESET 0x6443
+#define LINUX_DRM_IOCTL_R128_CCE_IDLE 0x6444
+#define LINUX_DRM_IOCTL_R128_RESET 0x6446
+#define LINUX_DRM_IOCTL_R128_SWAP 0x6447
+#define LINUX_DRM_IOCTL_R128_CLEAR 0x6448
+#define LINUX_DRM_IOCTL_R128_VERTEX 0x6449
+#define LINUX_DRM_IOCTL_R128_INDICES 0x644a
+#define LINUX_DRM_IOCTL_R128_BLIT 0x644b
+#define LINUX_DRM_IOCTL_R128_DEPTH 0x644c
+#define LINUX_DRM_IOCTL_R128_STIPPLE 0x644d
+#define LINUX_DRM_IOCTL_R128_INDIRECT 0x644f
+#define LINUX_DRM_IOCTL_R128_FULLSCREEN 0x6450
+
+/* Radeon specific ioctls */
+#define LINUX_DRM_IOCTL_RADEON_CP_INIT 0x6440
+#define LINUX_DRM_IOCTL_RADEON_CP_START 0x6441
+#define LINUX_DRM_IOCTL_RADEON_CP_STOP 0x6442
+#define LINUX_DRM_IOCTL_RADEON_CP_RESET 0x6443
+#define LINUX_DRM_IOCTL_RADEON_CP_IDLE 0x6444
+#define LINUX_DRM_IOCTL_RADEON_RESET 0x6445
+#define LINUX_DRM_IOCTL_RADEON_FULLSCREEN 0x6446
+#define LINUX_DRM_IOCTL_RADEON_SWAP 0x6447
+#define LINUX_DRM_IOCTL_RADEON_CLEAR 0x6448
+#define LINUX_DRM_IOCTL_RADEON_VERTEX 0x6449
+#define LINUX_DRM_IOCTL_RADEON_INDICES 0x644a
+#define LINUX_DRM_IOCTL_RADEON_STIPPLE 0x644c
+#define LINUX_DRM_IOCTL_RADEON_INDIRECT 0x644d
+#define LINUX_DRM_IOCTL_RADEON_TEXTURE 0x644e
+
+/* card specific ioctls may increase the DRM_MAX */
+#define LINUX_IOCTL_DRM_MIN LINUX_DRM_IOCTL_VERSION
+#define LINUX_IOCTL_DRM_MAX LINUX_DRM_IOCTL_R128_FULLSCREEN
diff --git a/sys/dev/drm/drm_lists.h b/sys/dev/drm/drm_lists.h
new file mode 100644
index 0000000..c0c819b
--- /dev/null
+++ b/sys/dev/drm/drm_lists.h
@@ -0,0 +1,304 @@
+/* drm_lists.h -- Buffer list handling routines -*- linux-c -*-
+ * Created: Mon Apr 19 20:54:22 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/drmP.h"
+
+#if __HAVE_DMA_WAITLIST
+
+int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
+{
+ if (bl->count)
+ DRM_OS_RETURN( EINVAL );
+
+ bl->bufs = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
+ DRM_MEM_BUFLISTS);
+
+ if(!bl->bufs) DRM_OS_RETURN(ENOMEM);
+
+ bl->count = count;
+ bl->rp = bl->bufs;
+ bl->wp = bl->bufs;
+ bl->end = &bl->bufs[bl->count+1];
+ DRM_OS_SPININIT( bl->write_lock, "writelock" );
+ DRM_OS_SPININIT( bl->read_lock, "readlock" );
+ return 0;
+}
+
+int DRM(waitlist_destroy)(drm_waitlist_t *bl)
+{
+ if (bl->rp != bl->wp)
+ DRM_OS_RETURN( EINVAL );
+ if (bl->bufs) DRM(free)(bl->bufs,
+ (bl->count + 2) * sizeof(*bl->bufs),
+ DRM_MEM_BUFLISTS);
+ bl->count = 0;
+ bl->bufs = NULL;
+ bl->rp = NULL;
+ bl->wp = NULL;
+ bl->end = NULL;
+ return 0;
+}
+
+int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
+{
+ int left;
+#ifdef __linux__
+ unsigned long flags;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ int s;
+#endif /* __FreeBSD__ */
+ left = DRM_LEFTCOUNT(bl);
+ if (!left) {
+ DRM_ERROR("Overflow while adding buffer %d from pid %d\n",
+ buf->idx, buf->pid);
+ DRM_OS_RETURN( EINVAL );
+ }
+#if __HAVE_DMA_HISTOGRAM
+#ifdef __linux__
+ buf->time_queued = get_cycles();
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ getnanotime(&buf->time_queued);
+#endif /* __FreeBSD__ */
+#endif
+ buf->list = DRM_LIST_WAIT;
+
+#ifdef __linux__
+ spin_lock_irqsave(&bl->write_lock, flags);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM_OS_SPINLOCK(&bl->write_lock);
+ s = spldrm();
+#endif /* __FreeBSD__ */
+ *bl->wp = buf;
+ if (++bl->wp >= bl->end) bl->wp = bl->bufs;
+#ifdef __linux__
+ spin_unlock_irqrestore(&bl->write_lock, flags);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ splx(s);
+ DRM_OS_SPINUNLOCK(&bl->write_lock);
+#endif /* __FreeBSD__ */
+
+ return 0;
+}
+
+drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl)
+{
+ drm_buf_t *buf;
+#ifdef __linux__
+ unsigned long flags;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ int s;
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+ spin_lock_irqsave(&bl->read_lock, flags);
+ buf = *bl->rp;
+ if (bl->rp == bl->wp) {
+ spin_unlock_irqrestore(&bl->read_lock, flags);
+ return NULL;
+ }
+ if (++bl->rp >= bl->end) bl->rp = bl->bufs;
+ spin_unlock_irqrestore(&bl->read_lock, flags);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM_OS_SPINLOCK(&bl->read_lock);
+ s = spldrm();
+ buf = *bl->rp;
+ if (bl->rp == bl->wp) {
+ splx(s);
+ DRM_OS_SPINUNLOCK(&bl->read_lock);
+ return NULL;
+ }
+ if (++bl->rp >= bl->end) bl->rp = bl->bufs;
+ splx(s);
+ DRM_OS_SPINUNLOCK(&bl->read_lock);
+#endif /* __FreeBSD__ */
+
+ return buf;
+}
+
+#endif /* __HAVE_DMA_WAITLIST */
+
+
+#if __HAVE_DMA_FREELIST
+
+int DRM(freelist_create)(drm_freelist_t *bl, int count)
+{
+ atomic_set(&bl->count, 0);
+ bl->next = NULL;
+#ifdef __linux__
+ init_waitqueue_head(&bl->waiting);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ bl->waiting = 0;
+#endif /* __FreeBSD__ */
+
+ bl->low_mark = 0;
+ bl->high_mark = 0;
+ atomic_set(&bl->wfh, 0);
+ DRM_OS_SPININIT( bl->lock, "freelistlock" );
+ ++bl->initialized;
+ return 0;
+}
+
+int DRM(freelist_destroy)(drm_freelist_t *bl)
+{
+ atomic_set(&bl->count, 0);
+ bl->next = NULL;
+ return 0;
+}
+
+int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
+{
+ drm_device_dma_t *dma = dev->dma;
+
+ if (!dma) {
+ DRM_ERROR("No DMA support\n");
+ return 1;
+ }
+
+ if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
+ DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
+ buf->idx, buf->waiting, buf->pending, buf->list);
+ }
+ if (!bl) return 1;
+#if __HAVE_DMA_HISTOGRAM
+#ifdef __linux__
+ buf->time_freed = get_cycles();
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ getnanotime(&buf->time_queued);
+#endif /* __FreeBSD__ */
+ DRM(histogram_compute)(dev, buf);
+#endif
+ buf->list = DRM_LIST_FREE;
+
+ DRM_OS_SPINLOCK( &bl->lock );
+ buf->next = bl->next;
+ bl->next = buf;
+ DRM_OS_SPINUNLOCK( &bl->lock );
+
+ atomic_inc(&bl->count);
+ if (atomic_read(&bl->count) > dma->buf_count) {
+ DRM_ERROR("%ld of %d buffers free after addition of %d\n",
+ (unsigned long)atomic_read(&bl->count),
+ dma->buf_count, buf->idx);
+ return 1;
+ }
+ /* Check for high water mark */
+ if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
+ atomic_set(&bl->wfh, 0);
+ DRM_OS_WAKEUP_INT(&bl->waiting);
+ }
+ return 0;
+}
+
+static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl)
+{
+ drm_buf_t *buf;
+
+ if (!bl) return NULL;
+
+ /* Get buffer */
+ DRM_OS_SPINLOCK(&bl->lock);
+ if (!bl->next) {
+ DRM_OS_SPINUNLOCK(&bl->lock);
+ return NULL;
+ }
+ buf = bl->next;
+ bl->next = bl->next->next;
+ DRM_OS_SPINUNLOCK(&bl->lock);
+
+ atomic_dec(&bl->count);
+ buf->next = NULL;
+ buf->list = DRM_LIST_NONE;
+ if (buf->waiting || buf->pending) {
+ DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
+ buf->idx, buf->waiting, buf->pending, buf->list);
+ }
+
+ return buf;
+}
+
+drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block)
+{
+ drm_buf_t *buf = NULL;
+#ifdef __linux__
+ DECLARE_WAITQUEUE(entry, current);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ int error;
+#endif /* __FreeBSD__ */
+
+ if (!bl || !bl->initialized) return NULL;
+
+ /* Check for low water mark */
+ if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
+ atomic_set(&bl->wfh, 1);
+ if (atomic_read(&bl->wfh)) {
+ if (block) {
+#ifdef __linux__
+ add_wait_queue(&bl->waiting, &entry);
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ if (!atomic_read(&bl->wfh)
+ && (buf = DRM(freelist_try)(bl))) break;
+ schedule();
+ if (signal_pending(current)) break;
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&bl->waiting, &entry);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ for (;;) {
+ if (!atomic_read(&bl->wfh)
+ && (buf = DRM(freelist_try(bl)))) break;
+ error = tsleep(&bl->waiting, PZERO|PCATCH,
+ "drmfg", 0);
+ if (error)
+ break;
+ }
+#endif /* __FreeBSD__ */
+ }
+ return buf;
+ }
+
+ return DRM(freelist_try)(bl);
+}
+
+#endif /* __HAVE_DMA_FREELIST */
diff --git a/sys/dev/drm/drm_lock.h b/sys/dev/drm/drm_lock.h
new file mode 100644
index 0000000..e3b1f5e
--- /dev/null
+++ b/sys/dev/drm/drm_lock.h
@@ -0,0 +1,314 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/drmP.h"
+
+int DRM(block)( DRM_OS_IOCTL )
+{
+ DRM_DEBUG("\n");
+ return 0;
+}
+
+int DRM(unblock)( DRM_OS_IOCTL )
+{
+ DRM_DEBUG("\n");
+ return 0;
+}
+
+int DRM(lock_take)(__volatile__ unsigned int *lock, unsigned int context)
+{
+ unsigned int old, new;
+#ifdef __linux__
+ unsigned int prev;
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+ char failed;
+#endif /* __FreeBSD__ */
+
+ do {
+ old = *lock;
+ if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
+ else new = context | _DRM_LOCK_HELD;
+#ifdef __linux__
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ _DRM_CAS(lock, old, new, failed);
+ } while (failed);
+#endif /* __FreeBSD__ */
+ 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;
+#ifdef __linux__
+ unsigned int prev;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ char failed;
+#endif /* __FreeBSD__ */
+
+ dev->lock.pid = 0;
+ do {
+ old = *lock;
+ new = context | _DRM_LOCK_HELD;
+#ifdef __linux__
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ _DRM_CAS(lock, old, new, failed);
+ } while (failed);
+#endif /* __FreeBSD__ */
+ return 1;
+}
+
+int DRM(lock_free)(drm_device_t *dev,
+ __volatile__ unsigned int *lock, unsigned int context)
+{
+ unsigned int old, new;
+#ifdef __linux__
+ unsigned int prev;
+#endif /* __linux__ */
+ pid_t pid = dev->lock.pid;
+#ifdef __FreeBSD__
+ char failed;
+#endif /* __FreeBSD__ */
+
+ dev->lock.pid = 0;
+ do {
+ old = *lock;
+ new = 0;
+#ifdef __linux__
+ prev = cmpxchg(lock, old, new);
+ } while (prev != old);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ _DRM_CAS(lock, old, new, failed);
+ } while (failed);
+#endif /* __FreeBSD__ */
+ if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
+ DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n",
+ context,
+ _DRM_LOCKING_CONTEXT(old),
+ pid);
+ return 1;
+ }
+ DRM_OS_WAKEUP_INT(&dev->lock.lock_queue);
+ return 0;
+}
+
+static int DRM(flush_queue)(drm_device_t *dev, int context)
+{
+#ifdef __linux__
+ DECLARE_WAITQUEUE(entry, current);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ int error;
+#endif /* __FreeBSD__ */
+ int ret = 0;
+ drm_queue_t *q = dev->queuelist[context];
+
+ DRM_DEBUG("\n");
+
+ atomic_inc(&q->use_count);
+ if (atomic_read(&q->use_count) > 1) {
+ atomic_inc(&q->block_write);
+#ifdef __linux__
+ add_wait_queue(&q->flush_queue, &entry);
+ atomic_inc(&q->block_count);
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ if (!DRM_BUFCOUNT(&q->waitlist)) break;
+ schedule();
+ if (signal_pending(current)) {
+ ret = -EINTR; /* Can't restart */
+ break;
+ }
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ atomic_inc(&q->block_count);
+ error = tsleep(&q->flush_queue, PZERO|PCATCH, "drmfq", 0);
+ if (error)
+ return error;
+#endif /* __FreeBSD__ */
+ atomic_dec(&q->block_count);
+#ifdef __linux__
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&q->flush_queue, &entry);
+#endif /* __linux__ */
+ }
+ atomic_dec(&q->use_count);
+
+ /* NOTE: block_write is still incremented!
+ Use drm_flush_unlock_queue to decrement. */
+ return ret;
+}
+
+static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
+{
+ drm_queue_t *q = dev->queuelist[context];
+
+ DRM_DEBUG("\n");
+
+ atomic_inc(&q->use_count);
+ if (atomic_read(&q->use_count) > 1) {
+ if (atomic_read(&q->block_write)) {
+ atomic_dec(&q->block_write);
+ DRM_OS_WAKEUP_INT(&q->write_queue);
+ }
+ }
+ atomic_dec(&q->use_count);
+ return 0;
+}
+
+int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
+ drm_lock_flags_t flags)
+{
+ int ret = 0;
+ int i;
+
+ DRM_DEBUG("\n");
+
+ if (flags & _DRM_LOCK_FLUSH) {
+ ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
+ if (!ret) ret = DRM(flush_queue)(dev, context);
+ }
+ if (flags & _DRM_LOCK_FLUSH_ALL) {
+ for (i = 0; !ret && i < dev->queue_count; i++) {
+ ret = DRM(flush_queue)(dev, i);
+ }
+ }
+ return ret;
+}
+
+int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
+{
+ int ret = 0;
+ int i;
+
+ DRM_DEBUG("\n");
+
+ if (flags & _DRM_LOCK_FLUSH) {
+ ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
+ if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
+ }
+ if (flags & _DRM_LOCK_FLUSH_ALL) {
+ for (i = 0; !ret && i < dev->queue_count; i++) {
+ ret = DRM(flush_unblock_queue)(dev, i);
+ }
+ }
+
+ return ret;
+}
+
+int DRM(finish)( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ int ret = 0;
+ drm_lock_t lock;
+
+ DRM_DEBUG("\n");
+
+ DRM_OS_KRNFROMUSR( lock, (drm_lock_t *)data, sizeof(lock) );
+
+ ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
+ DRM(flush_unblock)(dev, lock.context, lock.flags);
+ return ret;
+}
+
+/* If we get here, it means that the process has called DRM_IOCTL_LOCK
+ without calling DRM_IOCTL_UNLOCK.
+
+ If the lock is not held, then let the signal proceed as usual.
+
+ If the lock is held, then set the contended flag and keep the signal
+ blocked.
+
+
+ Return 1 if the signal should be delivered normally.
+ Return 0 if the signal should be blocked. */
+
+int DRM(notifier)(void *priv)
+{
+ drm_sigdata_t *s = (drm_sigdata_t *)priv;
+ unsigned int old, new;
+#ifdef __linux__
+ unsigned int prev;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ char failed;
+#endif /* __FreeBSD__ */
+
+
+ /* Allow signal delivery if lock isn't held */
+ if (!_DRM_LOCK_IS_HELD(s->lock->lock)
+ || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
+
+ /* Otherwise, set flag to force call to
+ drmUnlock */
+ do {
+ old = s->lock->lock;
+ new = old | _DRM_LOCK_CONT;
+#ifdef __linux__
+ prev = cmpxchg(&s->lock->lock, old, new);
+ } while (prev != old);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ _DRM_CAS(&s->lock->lock, old, new, failed);
+ } while (failed);
+#endif /* __FreeBSD__ */
+ return 0;
+}
+
diff --git a/sys/dev/drm/drm_memory.h b/sys/dev/drm/drm_memory.h
new file mode 100644
index 0000000..51e99e3
--- /dev/null
+++ b/sys/dev/drm/drm_memory.h
@@ -0,0 +1,595 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#ifdef __linux__
+#include <linux/config.h>
+#endif /* __linux__ */
+#include "dev/drm/drmP.h"
+#ifdef __linux__
+#include <linux/wrapper.h>
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#if __REALLY_HAVE_AGP
+#include <sys/agpio.h>
+#endif
+
+#define malloctype DRM(M_DRM)
+/* The macros confliced in the MALLOC_DEFINE */
+
+MALLOC_DEFINE(malloctype, "drm", "DRM Data Structures");
+
+#undef malloctype
+#endif /* __FreeBSD__ */
+
+typedef struct drm_mem_stats {
+ const char *name;
+ int succeed_count;
+ int free_count;
+ int fail_count;
+ unsigned long bytes_allocated;
+ unsigned long bytes_freed;
+} drm_mem_stats_t;
+
+#ifdef __linux__
+static spinlock_t DRM(mem_lock) = SPIN_LOCK_UNLOCKED;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+static DRM_OS_SPINTYPE DRM(mem_lock);
+#endif /* __FreeBSD__ */
+static unsigned long DRM(ram_available) = 0; /* In pages */
+static unsigned long DRM(ram_used) = 0;
+static drm_mem_stats_t DRM(mem_stats)[] = {
+ [DRM_MEM_DMA] = { "dmabufs" },
+ [DRM_MEM_SAREA] = { "sareas" },
+ [DRM_MEM_DRIVER] = { "driver" },
+ [DRM_MEM_MAGIC] = { "magic" },
+ [DRM_MEM_IOCTLS] = { "ioctltab" },
+ [DRM_MEM_MAPS] = { "maplist" },
+ [DRM_MEM_VMAS] = { "vmalist" },
+ [DRM_MEM_BUFS] = { "buflist" },
+ [DRM_MEM_SEGS] = { "seglist" },
+ [DRM_MEM_PAGES] = { "pagelist" },
+ [DRM_MEM_FILES] = { "files" },
+ [DRM_MEM_QUEUES] = { "queues" },
+ [DRM_MEM_CMDS] = { "commands" },
+ [DRM_MEM_MAPPINGS] = { "mappings" },
+ [DRM_MEM_BUFLISTS] = { "buflists" },
+ [DRM_MEM_AGPLISTS] = { "agplist" },
+ [DRM_MEM_SGLISTS] = { "sglist" },
+ [DRM_MEM_TOTALAGP] = { "totalagp" },
+ [DRM_MEM_BOUNDAGP] = { "boundagp" },
+ [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
+ [DRM_MEM_STUB] = { "stub" },
+ { NULL, 0, } /* Last entry must be null */
+};
+
+void DRM(mem_init)(void)
+{
+ drm_mem_stats_t *mem;
+#ifdef __linux__
+ struct sysinfo si;
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+ DRM_OS_SPININIT(DRM(mem_lock), "drm memory");
+#endif /* __FreeBSD__ */
+
+ for (mem = DRM(mem_stats); mem->name; ++mem) {
+ mem->succeed_count = 0;
+ mem->free_count = 0;
+ mem->fail_count = 0;
+ mem->bytes_allocated = 0;
+ mem->bytes_freed = 0;
+ }
+
+#ifdef __linux__
+ si_meminfo(&si);
+ DRM(ram_available) = si.totalram;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM(ram_available) = 0; /* si.totalram */
+#endif /* __FreeBSD__ */
+ DRM(ram_used) = 0;
+}
+
+/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
+#ifdef __linux__
+static int DRM(_mem_info)(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ drm_mem_stats_t *pt;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *eof = 0;
+ *start = &buf[offset];
+
+ DRM_PROC_PRINT(" total counts "
+ " | outstanding \n");
+ DRM_PROC_PRINT("type alloc freed fail bytes freed"
+ " | allocs bytes\n\n");
+ DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
+ "system", 0, 0, 0,
+ DRM(ram_available) << (PAGE_SHIFT - 10));
+ DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
+ "locked", 0, 0, 0, DRM(ram_used) >> 10);
+ DRM_PROC_PRINT("\n");
+ for (pt = DRM(mem_stats); pt->name; pt++) {
+ DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
+ pt->name,
+ pt->succeed_count,
+ pt->free_count,
+ pt->fail_count,
+ pt->bytes_allocated,
+ pt->bytes_freed,
+ pt->succeed_count - pt->free_count,
+ (long)pt->bytes_allocated
+ - (long)pt->bytes_freed);
+ }
+
+ if (len > request + offset) return request;
+ *eof = 1;
+ return len - offset;
+}
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+static int DRM(_mem_info) DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_mem_stats_t *pt;
+ char buf[128];
+ int error;
+
+ DRM_SYSCTL_PRINT(" total counts "
+ " | outstanding \n");
+ DRM_SYSCTL_PRINT("type alloc freed fail bytes freed"
+ " | allocs bytes\n\n");
+ DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n",
+ "system", 0, 0, 0, DRM(ram_available));
+ DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n",
+ "locked", 0, 0, 0, DRM(ram_used));
+ DRM_SYSCTL_PRINT("\n");
+ for (pt = DRM(mem_stats); pt->name; pt++) {
+ DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
+ pt->name,
+ pt->succeed_count,
+ pt->free_count,
+ pt->fail_count,
+ pt->bytes_allocated,
+ pt->bytes_freed,
+ pt->succeed_count - pt->free_count,
+ (long)pt->bytes_allocated
+ - (long)pt->bytes_freed);
+ }
+ SYSCTL_OUT(req, "", 1);
+
+ return 0;
+}
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+int DRM(mem_info)(char *buf, char **start, off_t offset,
+ int len, int *eof, void *data)
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS
+#endif /* __FreeBSD__ */
+{
+ int ret;
+
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+#ifdef __linux__
+ ret = DRM(_mem_info)(buf, start, offset, len, eof, data);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ ret = DRM(_mem_info)(oidp, arg1, arg2, req);
+#endif /* __FreeBSD__ */
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return ret;
+}
+
+void *DRM(alloc)(size_t size, int area)
+{
+ void *pt;
+
+ if (!size) {
+ DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
+ return NULL;
+ }
+
+#ifdef __linux__
+ if (!(pt = kmalloc(size, GFP_KERNEL))) {
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if (!(pt = malloc(size, DRM(M_DRM), M_NOWAIT))) {
+#endif /* __FreeBSD__ */
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[area].fail_count;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return NULL;
+ }
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[area].succeed_count;
+ DRM(mem_stats)[area].bytes_allocated += size;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return pt;
+}
+
+void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
+{
+ void *pt;
+
+ if (!(pt = DRM(alloc)(size, area))) return NULL;
+ if (oldpt && oldsize) {
+ memcpy(pt, oldpt, oldsize);
+ DRM(free)(oldpt, oldsize, area);
+ }
+ return pt;
+}
+
+char *DRM(strdup)(const char *s, int area)
+{
+ char *pt;
+ int length = s ? strlen(s) : 0;
+
+ if (!(pt = DRM(alloc)(length+1, area))) return NULL;
+ strcpy(pt, s);
+ return pt;
+}
+
+void DRM(strfree)(char *s, int area)
+{
+ unsigned int size;
+
+ if (!s) return;
+
+ size = 1 + strlen(s);
+ DRM(free)((void *)s, size, area);
+}
+
+void DRM(free)(void *pt, size_t size, int area)
+{
+ int alloc_count;
+ int free_count;
+
+ if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
+#ifdef __linux__
+ else kfree(pt);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ else free(pt, DRM(M_DRM));
+#endif /* __FreeBSD__ */
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ DRM(mem_stats)[area].bytes_freed += size;
+ free_count = ++DRM(mem_stats)[area].free_count;
+ alloc_count = DRM(mem_stats)[area].succeed_count;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+}
+
+unsigned long DRM(alloc_pages)(int order, int area)
+{
+#ifdef __linux__
+ unsigned long address;
+ unsigned long addr;
+ unsigned int sz;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ vm_offset_t address;
+#endif /* __FreeBSD__ */
+ unsigned long bytes = PAGE_SIZE << order;
+
+#ifdef __linux__
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ if ((DRM(ram_used) >> PAGE_SHIFT)
+ > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) {
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return 0;
+ }
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+#endif /* __linux__ */
+
+#ifdef __linux__
+ address = __get_free_pages(GFP_KERNEL, order);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ address = (vm_offset_t) contigmalloc(bytes, DRM(M_DRM), M_WAITOK, 0, ~0, 1, 0);
+#endif /* __FreeBSD__ */
+ if (!address) {
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[area].fail_count;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return 0;
+ }
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[area].succeed_count;
+ DRM(mem_stats)[area].bytes_allocated += bytes;
+ DRM(ram_used) += bytes;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+
+
+ /* Zero outside the lock */
+ memset((void *)address, 0, bytes);
+
+#ifdef __linux__
+ /* Reserve */
+ for (addr = address, sz = bytes;
+ sz > 0;
+ addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ mem_map_reserve(virt_to_page(addr));
+ }
+#endif /* __linux__ */
+
+ return address;
+}
+
+void DRM(free_pages)(unsigned long address, int order, int area)
+{
+ unsigned long bytes = PAGE_SIZE << order;
+ int alloc_count;
+ int free_count;
+
+ if (!address) {
+ DRM_MEM_ERROR(area, "Attempt to free address 0\n");
+ } else {
+#ifdef __linux__
+ unsigned long addr;
+ unsigned int sz;
+ /* Unreserve */
+ for (addr = address, sz = bytes;
+ sz > 0;
+ addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ mem_map_unreserve(virt_to_page(addr));
+ }
+ free_pages(address, order);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ contigfree((void *) address, bytes, DRM(M_DRM));
+#endif /* __FreeBSD__ */
+ }
+
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ free_count = ++DRM(mem_stats)[area].free_count;
+ alloc_count = DRM(mem_stats)[area].succeed_count;
+ DRM(mem_stats)[area].bytes_freed += bytes;
+ DRM(ram_used) -= bytes;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(area,
+ "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+}
+
+void *DRM(ioremap)(unsigned long offset, unsigned long size)
+{
+ void *pt;
+
+ if (!size) {
+ DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+ "Mapping 0 bytes at 0x%08lx\n", offset);
+ return NULL;
+ }
+
+#ifdef __linux__
+ if (!(pt = ioremap(offset, size))) {
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if (!(pt = pmap_mapdev(offset, size))) {
+#endif /* __FreeBSD__ */
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return NULL;
+ }
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
+ DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return pt;
+}
+
+void DRM(ioremapfree)(void *pt, unsigned long size)
+{
+ int alloc_count;
+ int free_count;
+
+ if (!pt)
+ DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+ "Attempt to free NULL pointer\n");
+ else
+#ifdef __linux__
+ iounmap(pt);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ pmap_unmapdev((vm_offset_t) pt, size);
+#endif /* __FreeBSD__ */
+
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;
+ free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
+ alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+ "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+}
+
+#if __REALLY_HAVE_AGP
+agp_memory *DRM(alloc_agp)(int pages, u32 type)
+{
+ agp_memory *handle;
+
+ if (!pages) {
+ DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
+ return NULL;
+ }
+
+ if ((handle = DRM(agp_allocate_memory)(pages, type))) {
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
+ DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
+ += pages << PAGE_SHIFT;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return handle;
+ }
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ return NULL;
+}
+
+int DRM(free_agp)(agp_memory *handle, int pages)
+{
+ int alloc_count;
+ int free_count;
+
+ if (!handle) {
+ DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+ "Attempt to free NULL AGP handle\n");
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ if (DRM(agp_free_memory)(handle)) {
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
+ alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
+ DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
+ += pages << PAGE_SHIFT;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+ "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+ return 0;
+ }
+ DRM_OS_RETURN(EINVAL);
+}
+
+int DRM(bind_agp)(agp_memory *handle, unsigned int start)
+{
+ int retcode;
+#ifdef __FreeBSD__
+ device_t dev = agp_find_device();
+ struct agp_memory_info info;
+
+ if (!dev)
+ return EINVAL;
+#endif /* __FreeBSD__ */
+
+ if (!handle) {
+ DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+ "Attempt to bind NULL AGP handle\n");
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
+#ifdef __linux__
+ DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
+ += handle->page_count << PAGE_SHIFT;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ agp_memory_info(dev, handle, &info);
+ DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
+ += info.ami_size;
+#endif /* __FreeBSD__ */
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ DRM_OS_RETURN(0);
+ }
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ DRM_OS_RETURN(retcode);
+}
+
+int DRM(unbind_agp)(agp_memory *handle)
+{
+ int alloc_count;
+ int free_count;
+ int retcode = EINVAL;
+#ifdef __FreeBSD__
+ device_t dev = agp_find_device();
+ struct agp_memory_info info;
+
+ if (!dev)
+ return EINVAL;
+#endif /* __FreeBSD__ */
+
+ if (!handle) {
+ DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+ "Attempt to unbind NULL AGP handle\n");
+ DRM_OS_RETURN(retcode);
+ }
+
+#ifdef __FreeBSD__
+ agp_memory_info(dev, handle, &info);
+#endif /* __FreeBSD__ */
+
+ if ((retcode = DRM(agp_unbind_memory)(handle)))
+ DRM_OS_RETURN(retcode);
+
+ DRM_OS_SPINLOCK(&DRM(mem_lock));
+ free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
+ alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
+#ifdef __linux__
+ DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
+ += handle->page_count << PAGE_SHIFT;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
+ += info.ami_size;
+#endif /* __FreeBSD__ */
+ DRM_OS_SPINUNLOCK(&DRM(mem_lock));
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+ "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+ DRM_OS_RETURN(retcode);
+}
+#endif
diff --git a/sys/dev/drm/drm_os_freebsd.h b/sys/dev/drm/drm_os_freebsd.h
new file mode 100644
index 0000000..5c2483a
--- /dev/null
+++ b/sys/dev/drm/drm_os_freebsd.h
@@ -0,0 +1,382 @@
+/*
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <sys/filio.h>
+#include <sys/sysctl.h>
+#include <sys/select.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/pmap.h>
+#if __FreeBSD_version >= 500000
+#include <sys/selinfo.h>
+#endif
+#include <sys/bus.h>
+#if __FreeBSD_version >= 400005
+#include <sys/taskqueue.h>
+#endif
+#if __FreeBSD_version >= 500000
+#include <sys/mutex.h>
+#endif
+
+#if __FreeBSD_version >= 400006
+#define __REALLY_HAVE_AGP __HAVE_AGP
+#endif
+
+#define __REALLY_HAVE_MTRR 0
+#define __REALLY_HAVE_SG 0
+
+#if __REALLY_HAVE_AGP
+#include <pci/agpvar.h>
+#endif
+
+/* Allow setting of debug code enabling from kernel config file */
+#include <opt_drm.h>
+#if DRM_DEBUG
+#undef DRM_DEBUG_CODE
+#define DRM_DEBUG_CODE 2
+#endif
+#undef DRM_DEBUG
+
+#define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */
+
+#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+#define DRM_DEV_UID 0
+#define DRM_DEV_GID 0
+
+#if __FreeBSD_version >= 500000
+#define DRM_OS_SPINTYPE struct mtx
+#define DRM_OS_SPININIT(l,name) mtx_init(&l, name, NULL, MTX_DEF)
+#define DRM_OS_SPINLOCK(l) mtx_lock(l)
+#define DRM_OS_SPINUNLOCK(u) mtx_unlock(u);
+#define DRM_OS_CURPROC curthread
+#define DRM_OS_STRUCTPROC struct thread
+#define DRM_OS_CURRENTPID curthread->td_proc->p_pid
+#else
+#define DRM_OS_CURPROC curproc
+#define DRM_OS_STRUCTPROC struct proc
+#define DRM_OS_SPINTYPE struct simplelock
+#define DRM_OS_SPININIT(l,name) simple_lock_init(&l)
+#define DRM_OS_SPINLOCK(l) simple_lock(l)
+#define DRM_OS_SPINUNLOCK(u) simple_unlock(u);
+#define DRM_OS_CURRENTPID curproc->p_pid
+#endif
+
+#define DRM_OS_IOCTL dev_t kdev, u_long cmd, caddr_t data, int flags, DRM_OS_STRUCTPROC *p
+#define DRM_OS_LOCK lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, DRM_OS_CURPROC)
+#define DRM_OS_UNLOCK lockmgr(&dev->dev_lock, LK_RELEASE, 0, DRM_OS_CURPROC)
+#define DRM_OS_CHECKSUSER suser(p)
+#define DRM_OS_TASKQUEUE_ARGS void *dev, int pending
+#define DRM_OS_IRQ_ARGS void *device
+#define DRM_OS_DEVICE drm_device_t *dev = kdev->si_drv1
+#define DRM_OS_MALLOC(size) malloc( size, DRM(M_DRM), M_NOWAIT )
+#define DRM_OS_FREE(pt) free( pt, DRM(M_DRM) )
+#define DRM_OS_VTOPHYS(addr) vtophys(addr)
+
+#define DRM_OS_PRIV \
+ drm_file_t *priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p); \
+ if (!priv) { \
+ DRM_DEBUG("can't find authenticator\n"); \
+ return EINVAL; \
+ }
+
+#define DRM_OS_DELAY( udelay ) \
+do { \
+ struct timeval tv1, tv2; \
+ microtime(&tv1); \
+ do { \
+ microtime(&tv2); \
+ } \
+ while (((tv2.tv_sec-tv1.tv_sec)*1000000 + tv2.tv_usec - tv1.tv_usec) < udelay ); \
+} while (0)
+
+#define DRM_OS_RETURN(v) return v;
+
+
+#define DRM_OS_KRNTOUSR(arg1, arg2, arg3) \
+ *arg1 = arg2
+#define DRM_OS_KRNFROMUSR(arg1, arg2, arg3) \
+ arg1 = *arg2
+#define DRM_OS_COPYTOUSR(arg1, arg2, arg3) \
+ copyout(arg2, arg1, arg3)
+#define DRM_OS_COPYFROMUSR(arg1, arg2, arg3) \
+ copyin(arg2, arg1, arg3)
+
+#define DRM_OS_READMEMORYBARRIER \
+{ \
+ int xchangeDummy; \
+ DRM_DEBUG("%s\n", __FUNCTION__); \
+ __asm__ volatile(" push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy)); \
+ __asm__ volatile(" push %%eax ; push %%ebx ; push %%ecx ; push %%edx ;" \
+ " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;" \
+ " pop %%eax" : /* no outputs */ : /* no inputs */ ); \
+} while (0);
+
+#define DRM_OS_WRITEMEMORYBARRIER DRM_OS_READMEMORYBARRIER
+
+#define DRM_OS_WAKEUP(w) wakeup(w)
+#define DRM_OS_WAKEUP_INT(w) wakeup(w)
+
+#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+#define malloctype DRM(M_DRM)
+/* The macros confliced in the MALLOC_DEFINE */
+MALLOC_DECLARE(malloctype);
+#undef malloctype
+
+typedef struct drm_chipinfo
+{
+ int vendor;
+ int device;
+ int supported;
+ char *name;
+} drm_chipinfo_t;
+
+typedef unsigned long atomic_t;
+typedef u_int32_t cycles_t;
+typedef u_int32_t spinlock_t;
+typedef u_int32_t u32;
+typedef u_int16_t u16;
+typedef u_int8_t u8;
+#define atomic_set(p, v) (*(p) = (v))
+#define atomic_read(p) (*(p))
+#define atomic_inc(p) atomic_add_long(p, 1)
+#define atomic_dec(p) atomic_subtract_long(p, 1)
+#define atomic_add(n, p) atomic_add_long(p, n)
+#define atomic_sub(n, p) atomic_subtract_long(p, n)
+
+/* Fake this */
+static __inline unsigned int
+test_and_set_bit(int b, volatile unsigned long *p)
+{
+ int s = splhigh();
+ unsigned int m = 1<<b;
+ unsigned int r = *p & m;
+ *p |= m;
+ splx(s);
+ return r;
+}
+
+static __inline void
+clear_bit(int b, volatile unsigned long *p)
+{
+ atomic_clear_long(p + (b >> 5), 1 << (b & 0x1f));
+}
+
+static __inline void
+set_bit(int b, volatile unsigned long *p)
+{
+ atomic_set_long(p + (b >> 5), 1 << (b & 0x1f));
+}
+
+static __inline int
+test_bit(int b, volatile unsigned long *p)
+{
+ return p[b >> 5] & (1 << (b & 0x1f));
+}
+
+static __inline int
+find_first_zero_bit(volatile unsigned long *p, int max)
+{
+ int b;
+
+ for (b = 0; b < max; b += 32) {
+ if (p[b >> 5] != ~0) {
+ for (;;) {
+ if ((p[b >> 5] & (1 << (b & 0x1f))) == 0)
+ return b;
+ b++;
+ }
+ }
+ }
+ return max;
+}
+
+#define spldrm() spltty()
+
+#define memset(p, v, s) bzero(p, s)
+
+/*
+ * Fake out the module macros for versions of FreeBSD where they don't
+ * exist.
+ */
+#if (__FreeBSD_version < 500002 && __FreeBSD_version > 500000) || __FreeBSD_version < 420000
+/* FIXME: again, what's the exact date? */
+#define MODULE_VERSION(a,b) struct __hack
+#define MODULE_DEPEND(a,b,c,d,e) struct __hack
+
+#endif
+
+#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)
+#define _DRM_CAS(lock,old,new,__ret) \
+ do { \
+ int __dummy; /* Can't mark eax as clobbered */ \
+ __asm__ __volatile__( \
+ "lock ; cmpxchg %4,%1\n\t" \
+ "setnz %0" \
+ : "=d" (__ret), \
+ "=m" (__drm_dummy_lock(lock)), \
+ "=a" (__dummy) \
+ : "2" (old), \
+ "r" (new)); \
+ } while (0)
+
+/* Redefinitions to make templating easy */
+#define wait_queue_head_t long
+#define agp_memory void
+#define jiffies ticks
+
+ /* Macros to make printf easier */
+#define DRM_ERROR(fmt, arg...) \
+ printf("error: " "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
+#define DRM_MEM_ERROR(area, fmt, arg...) \
+ printf("error: " "[" DRM_NAME ":" __FUNCTION__ ":%s] *ERROR* " fmt , \
+ DRM(mem_stats)[area].name , ##arg)
+#define DRM_INFO(fmt, arg...) printf("info: " "[" DRM_NAME "] " fmt , ##arg)
+
+#if DRM_DEBUG_CODE
+#define DRM_DEBUG(fmt, arg...) \
+ do { \
+ if (DRM(flags) & DRM_FLAG_DEBUG) \
+ printf("[" DRM_NAME ":" __FUNCTION__ "] " fmt , \
+ ##arg); \
+ } while (0)
+#else
+#define DRM_DEBUG(fmt, arg...) do { } while (0)
+#endif
+
+#define DRM_PROC_LIMIT (PAGE_SIZE-80)
+
+#if (__FreeBSD_version >= 500000) || ((__FreeBSD_version < 500000) && (__FreeBSD_version >= 410002))
+#define DRM_SYSCTL_HANDLER_ARGS (SYSCTL_HANDLER_ARGS)
+#else
+#define DRM_SYSCTL_HANDLER_ARGS SYSCTL_HANDLER_ARGS
+#endif
+
+#define DRM_SYSCTL_PRINT(fmt, arg...) \
+ snprintf(buf, sizeof(buf), fmt, ##arg); \
+ error = SYSCTL_OUT(req, buf, strlen(buf)); \
+ if (error) return error;
+
+#define DRM_SYSCTL_PRINT_RET(ret, fmt, arg...) \
+ snprintf(buf, sizeof(buf), fmt, ##arg); \
+ error = SYSCTL_OUT(req, buf, strlen(buf)); \
+ if (error) { ret; return error; }
+
+
+#define DRM_FIND_MAP(dest, o) \
+ do { \
+ drm_map_list_entry_t *listentry; \
+ TAILQ_FOREACH(listentry, dev->maplist, link) { \
+ if ( listentry->map->offset == o ) { \
+ dest = listentry->map; \
+ break; \
+ } \
+ } \
+ } while (0)
+
+
+/* Internal functions */
+
+/* drm_drv.h */
+extern d_ioctl_t DRM(ioctl);
+extern d_ioctl_t DRM(lock);
+extern d_ioctl_t DRM(unlock);
+extern d_open_t DRM(open);
+extern d_close_t DRM(close);
+extern d_read_t DRM(read);
+extern d_write_t DRM(write);
+extern d_poll_t DRM(poll);
+extern d_mmap_t DRM(mmap);
+extern int DRM(open_helper)(dev_t kdev, int flags, int fmt,
+ DRM_OS_STRUCTPROC *p, drm_device_t *dev);
+extern drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev,
+ DRM_OS_STRUCTPROC *p);
+
+/* Misc. IOCTL support (drm_ioctl.h) */
+extern d_ioctl_t DRM(irq_busid);
+extern d_ioctl_t DRM(getunique);
+extern d_ioctl_t DRM(setunique);
+extern d_ioctl_t DRM(getmap);
+extern d_ioctl_t DRM(getclient);
+extern d_ioctl_t DRM(getstats);
+
+/* Context IOCTL support (drm_context.h) */
+extern d_ioctl_t DRM(resctx);
+extern d_ioctl_t DRM(addctx);
+extern d_ioctl_t DRM(modctx);
+extern d_ioctl_t DRM(getctx);
+extern d_ioctl_t DRM(switchctx);
+extern d_ioctl_t DRM(newctx);
+extern d_ioctl_t DRM(rmctx);
+extern d_ioctl_t DRM(setsareactx);
+extern d_ioctl_t DRM(getsareactx);
+
+/* Drawable IOCTL support (drm_drawable.h) */
+extern d_ioctl_t DRM(adddraw);
+extern d_ioctl_t DRM(rmdraw);
+
+/* Authentication IOCTL support (drm_auth.h) */
+extern d_ioctl_t DRM(getmagic);
+extern d_ioctl_t DRM(authmagic);
+
+/* Locking IOCTL support (drm_lock.h) */
+extern d_ioctl_t DRM(block);
+extern d_ioctl_t DRM(unblock);
+extern d_ioctl_t DRM(finish);
+
+/* Buffer management support (drm_bufs.h) */
+extern d_ioctl_t DRM(addmap);
+extern d_ioctl_t DRM(rmmap);
+#if __HAVE_DMA
+extern d_ioctl_t DRM(addbufs_agp);
+extern d_ioctl_t DRM(addbufs_pci);
+extern d_ioctl_t DRM(addbufs_sg);
+extern d_ioctl_t DRM(addbufs);
+extern d_ioctl_t DRM(infobufs);
+extern d_ioctl_t DRM(markbufs);
+extern d_ioctl_t DRM(freebufs);
+extern d_ioctl_t DRM(mapbufs);
+#endif
+
+/* Memory management support (drm_memory.h) */
+extern int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS;
+
+/* DMA support (drm_dma.h) */
+#if __HAVE_DMA_IRQ
+extern d_ioctl_t DRM(control);
+#endif
+
+/* AGP/GART support (drm_agpsupport.h) */
+#if __REALLY_HAVE_AGP
+extern d_ioctl_t DRM(agp_acquire);
+extern d_ioctl_t DRM(agp_release);
+extern d_ioctl_t DRM(agp_enable);
+extern d_ioctl_t DRM(agp_info);
+extern d_ioctl_t DRM(agp_alloc);
+extern d_ioctl_t DRM(agp_free);
+extern d_ioctl_t DRM(agp_unbind);
+extern d_ioctl_t DRM(agp_bind);
+#endif
+
+/* Scatter Gather Support (drm_scatter.h) */
+#if __HAVE_SG
+extern d_ioctl_t DRM(sg_alloc);
+extern d_ioctl_t DRM(sg_free);
+#endif
+
+/* SysCtl Support (drm_sysctl.h) */
+extern int DRM(sysctl_init)(drm_device_t *dev);
+extern int DRM(sysctl_cleanup)(drm_device_t *dev);
diff --git a/sys/dev/drm/drm_scatter.h b/sys/dev/drm/drm_scatter.h
new file mode 100644
index 0000000..2ad543c
--- /dev/null
+++ b/sys/dev/drm/drm_scatter.h
@@ -0,0 +1,239 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/vmalloc.h>
+#include "dev/drm/drmP.h"
+
+#define DEBUG_SCATTER 0
+
+void DRM(sg_cleanup)( drm_sg_mem_t *entry )
+{
+ struct page *page;
+ int i;
+
+ for ( i = 0 ; i < entry->pages ; i++ ) {
+ page = entry->pagelist[i];
+ if ( page )
+ ClearPageReserved( page );
+ }
+
+ vfree( entry->virtual );
+
+ DRM(free)( entry->busaddr,
+ entry->pages * sizeof(*entry->busaddr),
+ DRM_MEM_PAGES );
+ DRM(free)( entry->pagelist,
+ entry->pages * sizeof(*entry->pagelist),
+ DRM_MEM_PAGES );
+ DRM(free)( entry,
+ sizeof(*entry),
+ DRM_MEM_SGLISTS );
+}
+
+int DRM(sg_alloc)( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_scatter_gather_t request;
+ drm_sg_mem_t *entry;
+ unsigned long pages, i, j;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( dev->sg )
+ return -EINVAL;
+
+ if ( copy_from_user( &request,
+ (drm_scatter_gather_t *)arg,
+ sizeof(request) ) )
+ return -EFAULT;
+
+ entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
+ if ( !entry )
+ return -ENOMEM;
+
+ memset( entry, 0, sizeof(*entry) );
+
+ pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
+ DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
+
+ entry->pages = pages;
+ entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist),
+ DRM_MEM_PAGES );
+ if ( !entry->pagelist ) {
+ DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
+ return -ENOMEM;
+ }
+
+ entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr),
+ DRM_MEM_PAGES );
+ if ( !entry->busaddr ) {
+ DRM(free)( entry->pagelist,
+ entry->pages * sizeof(*entry->pagelist),
+ DRM_MEM_PAGES );
+ DRM(free)( entry,
+ sizeof(*entry),
+ DRM_MEM_SGLISTS );
+ return -ENOMEM;
+ }
+ memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
+
+ entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
+ if ( !entry->virtual ) {
+ DRM(free)( entry->busaddr,
+ entry->pages * sizeof(*entry->busaddr),
+ DRM_MEM_PAGES );
+ DRM(free)( entry->pagelist,
+ entry->pages * sizeof(*entry->pagelist),
+ DRM_MEM_PAGES );
+ DRM(free)( entry,
+ sizeof(*entry),
+ DRM_MEM_SGLISTS );
+ return -ENOMEM;
+ }
+
+ /* This also forces the mapping of COW pages, so our page list
+ * will be valid. Please don't remove it...
+ */
+ memset( entry->virtual, 0, pages << PAGE_SHIFT );
+
+ entry->handle = (unsigned long)entry->virtual;
+
+ DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
+ DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
+
+ for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
+ pgd = pgd_offset_k( i );
+ if ( !pgd_present( *pgd ) )
+ goto failed;
+
+ pmd = pmd_offset( pgd, i );
+ if ( !pmd_present( *pmd ) )
+ goto failed;
+
+ pte = pte_offset( pmd, i );
+ if ( !pte_present( *pte ) )
+ goto failed;
+
+ entry->pagelist[j] = pte_page( *pte );
+
+ SetPageReserved( entry->pagelist[j] );
+ }
+
+ request.handle = entry->handle;
+
+ if ( copy_to_user( (drm_scatter_gather_t *)arg,
+ &request,
+ sizeof(request) ) ) {
+ DRM(sg_cleanup)( entry );
+ return -EFAULT;
+ }
+
+ dev->sg = entry;
+
+#if DEBUG_SCATTER
+ /* Verify that each page points to its virtual address, and vice
+ * versa.
+ */
+ {
+ int error = 0;
+
+ for ( i = 0 ; i < pages ; i++ ) {
+ unsigned long *tmp;
+
+ tmp = page_address( entry->pagelist[i] );
+ for ( j = 0 ;
+ j < PAGE_SIZE / sizeof(unsigned long) ;
+ j++, tmp++ ) {
+ *tmp = 0xcafebabe;
+ }
+ tmp = (unsigned long *)((u8 *)entry->virtual +
+ (PAGE_SIZE * i));
+ for( j = 0 ;
+ j < PAGE_SIZE / sizeof(unsigned long) ;
+ j++, tmp++ ) {
+ if ( *tmp != 0xcafebabe && error == 0 ) {
+ error = 1;
+ DRM_ERROR( "Scatter allocation error, "
+ "pagelist does not match "
+ "virtual mapping\n" );
+ }
+ }
+ tmp = page_address( entry->pagelist[i] );
+ for(j = 0 ;
+ j < PAGE_SIZE / sizeof(unsigned long) ;
+ j++, tmp++) {
+ *tmp = 0;
+ }
+ }
+ if (error == 0)
+ DRM_ERROR( "Scatter allocation matches pagelist\n" );
+ }
+#endif
+
+ return 0;
+
+ failed:
+ DRM(sg_cleanup)( entry );
+ return -ENOMEM;
+}
+
+int DRM(sg_free)( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_scatter_gather_t request;
+ drm_sg_mem_t *entry;
+
+ if ( copy_from_user( &request,
+ (drm_scatter_gather_t *)arg,
+ sizeof(request) ) )
+ return -EFAULT;
+
+ entry = dev->sg;
+ dev->sg = NULL;
+
+ if ( !entry || entry->handle != request.handle )
+ return -EINVAL;
+
+ DRM_DEBUG( "sg free virtual = %p\n", entry->virtual );
+
+ DRM(sg_cleanup)( entry );
+
+ return 0;
+}
diff --git a/sys/dev/drm/drm_sysctl.h b/sys/dev/drm/drm_sysctl.h
new file mode 100644
index 0000000..776b21f
--- /dev/null
+++ b/sys/dev/drm/drm_sysctl.h
@@ -0,0 +1,525 @@
+/*
+ * $FreeBSD$
+ */
+
+#include "dev/drm/drm.h"
+#include "dev/drm/drmP.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(queues_info)DRM_SYSCTL_HANDLER_ARGS;
+static int DRM(bufs_info)DRM_SYSCTL_HANDLER_ARGS;
+#if DRM_DEBUG_CODExx
+static int DRM(vma_info)DRM_SYSCTL_HANDLER_ARGS;
+#endif
+#if DRM_DMA_HISTOGRAM
+static int DRM(histo_info)DRM_SYSCTL_HANDLER_ARGS;
+#endif
+
+struct DRM(sysctl_list) {
+ const char *name;
+ int (*f) DRM_SYSCTL_HANDLER_ARGS;
+} DRM(sysctl_list)[] = {
+ { "name", DRM(name_info) },
+ { "mem", DRM(mem_info) },
+ { "vm", DRM(vm_info) },
+ { "clients", DRM(clients_info) },
+ { "queues", DRM(queues_info) },
+ { "bufs", DRM(bufs_info) },
+#if DRM_DEBUG_CODExx
+ { "vma", DRM(vma_info) },
+#endif
+#if DRM_DMA_HISTOGRAM
+ { "histo", drm_histo_info) },
+#endif
+};
+#define DRM_SYSCTL_ENTRIES (sizeof(DRM(sysctl_list))/sizeof(DRM(sysctl_list)[0]))
+
+struct drm_sysctl_info {
+ struct sysctl_ctx_list ctx;
+ char name[2];
+};
+
+int DRM(sysctl_init)(drm_device_t *dev)
+{
+ struct drm_sysctl_info *info;
+ struct sysctl_oid *oid;
+ struct sysctl_oid *top, *drioid;
+ int i;
+
+ info = DRM(alloc)(sizeof *info, DRM_MEM_DRIVER);
+ if ( !info )
+ return 1;
+ bzero(info, sizeof *info);
+ dev->sysctl = info;
+
+ /* 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;
+ }
+ return 0;
+}
+
+int DRM(sysctl_cleanup)(drm_device_t *dev)
+{
+ int error;
+ error = sysctl_ctx_free( &dev->sysctl->ctx );
+
+ DRM(free)(dev->sysctl, sizeof *dev->sysctl, DRM_MEM_DRIVER);
+ dev->sysctl = NULL;
+
+ return error;
+}
+
+static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ char buf[128];
+ int error;
+
+ if (dev->unique) {
+ DRM_SYSCTL_PRINT("%s 0x%x %s\n",
+ dev->name, dev2udev(dev->devnode), dev->unique);
+ } else {
+ DRM_SYSCTL_PRINT("%s 0x%x\n", dev->name, dev2udev(dev->devnode));
+ }
+
+ SYSCTL_OUT(req, "", 1);
+
+ return 0;
+}
+
+static int DRM(_vm_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ drm_map_t *map;
+ drm_map_list_entry_t *listentry;
+ const char *types[] = { "FB", "REG", "SHM" };
+ const char *type;
+ int i=0;
+ char buf[128];
+ int error;
+
+ DRM_SYSCTL_PRINT("slot offset size type flags "
+ "address mtrr\n\n");
+ error = SYSCTL_OUT(req, buf, strlen(buf));
+ if (error) return error;
+
+ if (dev->maplist != NULL) {
+ TAILQ_FOREACH(listentry, dev->maplist, link) {
+ map = listentry->map;
+ if (map->type < 0 || map->type > 2) type = "??";
+ else type = types[map->type];
+ DRM_SYSCTL_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
+ i,
+ map->offset,
+ map->size,
+ type,
+ map->flags,
+ (unsigned long)map->handle);
+ if (map->mtrr < 0) {
+ DRM_SYSCTL_PRINT("none\n");
+ } else {
+ DRM_SYSCTL_PRINT("%4d\n", map->mtrr);
+ }
+ i++;
+ }
+ }
+ SYSCTL_OUT(req, "", 1);
+
+ return 0;
+}
+
+static int DRM(vm_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ int ret;
+
+ DRM_OS_LOCK;
+ ret = DRM(_vm_info)(oidp, arg1, arg2, req);
+ DRM_OS_UNLOCK;
+
+ return ret;
+}
+
+
+static int DRM(_queues_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ int i;
+ drm_queue_t *q;
+ char buf[128];
+ int error;
+
+ DRM_SYSCTL_PRINT(" ctx/flags use fin"
+ " blk/rw/rwf wait flushed queued"
+ " locks\n\n");
+ for (i = 0; i < dev->queue_count; i++) {
+ q = dev->queuelist[i];
+ atomic_inc(&q->use_count);
+ DRM_SYSCTL_PRINT_RET(atomic_dec(&q->use_count),
+ "%5d/0x%03x %5ld %5ld"
+ " %5ld/%c%c/%c%c%c %5d %10ld %10ld %10ld\n",
+ i,
+ q->flags,
+ atomic_read(&q->use_count),
+ atomic_read(&q->finalization),
+ atomic_read(&q->block_count),
+ atomic_read(&q->block_read) ? 'r' : '-',
+ atomic_read(&q->block_write) ? 'w' : '-',
+ q->read_queue ? 'r':'-',
+ q->write_queue ? 'w':'-',
+ q->flush_queue ? 'f':'-',
+ DRM_BUFCOUNT(&q->waitlist),
+ atomic_read(&q->total_flushed),
+ atomic_read(&q->total_queued),
+ atomic_read(&q->total_locks));
+ atomic_dec(&q->use_count);
+ }
+
+ SYSCTL_OUT(req, "", 1);
+ return 0;
+}
+
+static int DRM(queues_info) DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ int ret;
+
+ DRM_OS_LOCK;
+ ret = DRM(_queues_info)(oidp, arg1, arg2, req);
+ DRM_OS_UNLOCK;
+ return ret;
+}
+
+/* drm_bufs_info is called whenever a process reads
+ hw.dri.0.bufs. */
+
+static int DRM(_bufs_info) DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+ char buf[128];
+ int error;
+
+ if (!dma) return 0;
+ DRM_SYSCTL_PRINT(" o size count free segs pages kB\n\n");
+ for (i = 0; i <= DRM_MAX_ORDER; i++) {
+ if (dma->bufs[i].buf_count)
+ DRM_SYSCTL_PRINT("%2d %8d %5d %5ld %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", dma->buflist[i]->list);
+ }
+ DRM_SYSCTL_PRINT("\n");
+
+ SYSCTL_OUT(req, "", 1);
+ return 0;
+}
+
+static int DRM(bufs_info) DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ int ret;
+
+ DRM_OS_LOCK;
+ ret = DRM(_bufs_info)(oidp, arg1, arg2, req);
+ DRM_OS_UNLOCK;
+ return ret;
+}
+
+
+static int DRM(_clients_info) DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ drm_file_t *priv;
+ char buf[128];
+ int error;
+
+ DRM_SYSCTL_PRINT("a dev pid uid magic ioctls\n\n");
+ TAILQ_FOREACH(priv, &dev->files, link) {
+ 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);
+ return 0;
+}
+
+static int DRM(clients_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ int ret;
+
+ DRM_OS_LOCK;
+ ret = DRM(_clients_info)(oidp, arg1, arg2, req);
+ DRM_OS_UNLOCK;
+ return ret;
+}
+
+#if DRM_DEBUG_CODExx
+
+static int DRM(_vma_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ drm_vma_entry_t *pt;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long i;
+ struct vm_area_struct *vma;
+ unsigned long address;
+#if defined(__i386__)
+ unsigned int pgprot;
+#endif
+ char buf[128];
+ int error;
+
+ DRM_SYSCTL_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
+ atomic_read(&dev->vma_count),
+ high_memory, virt_to_phys(high_memory));
+ for (pt = dev->vmalist; pt; pt = pt->next) {
+ if (!(vma = pt->vma)) continue;
+ DRM_SYSCTL_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
+ pt->pid,
+ vma->vm_start,
+ vma->vm_end,
+ vma->vm_flags & VM_READ ? 'r' : '-',
+ vma->vm_flags & VM_WRITE ? 'w' : '-',
+ vma->vm_flags & VM_EXEC ? 'x' : '-',
+ vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
+ vma->vm_flags & VM_LOCKED ? 'l' : '-',
+ vma->vm_flags & VM_IO ? 'i' : '-',
+ vma->vm_offset );
+#if defined(__i386__)
+ pgprot = pgprot_val(vma->vm_page_prot);
+ DRM_SYSCTL_PRINT(" %c%c%c%c%c%c%c%c%c",
+ pgprot & _PAGE_PRESENT ? 'p' : '-',
+ pgprot & _PAGE_RW ? 'w' : 'r',
+ pgprot & _PAGE_USER ? 'u' : 's',
+ pgprot & _PAGE_PWT ? 't' : 'b',
+ pgprot & _PAGE_PCD ? 'u' : 'c',
+ pgprot & _PAGE_ACCESSED ? 'a' : '-',
+ pgprot & _PAGE_DIRTY ? 'd' : '-',
+ pgprot & _PAGE_4M ? 'm' : 'k',
+ pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
+#endif
+ DRM_SYSCTL_PRINT("\n");
+ for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
+ pgd = pgd_offset(vma->vm_mm, i);
+ pmd = pmd_offset(pgd, i);
+ pte = pte_offset(pmd, i);
+ if (pte_present(*pte)) {
+ address = __pa(pte_page(*pte))
+ + (i & (PAGE_SIZE-1));
+ DRM_SYSCTL_PRINT(" 0x%08lx -> 0x%08lx"
+ " %c%c%c%c%c\n",
+ i,
+ address,
+ pte_read(*pte) ? 'r' : '-',
+ pte_write(*pte) ? 'w' : '-',
+ pte_exec(*pte) ? 'x' : '-',
+ pte_dirty(*pte) ? 'd' : '-',
+ pte_young(*pte) ? 'a' : '-' );
+ } else {
+ DRM_SYSCTL_PRINT(" 0x%08lx\n", i);
+ }
+ }
+ }
+
+ SYSCTL_OUT(req, "", 1);
+ return 0;
+}
+
+static int DRM(vma_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ int ret;
+
+ DRM_OS_LOCK;
+ ret = DRM(_vma_info)(oidp, arg1, arg2, req);
+ DRM_OS_UNLOCK;
+ return ret;
+}
+#endif
+
+
+#if DRM_DMA_HISTOGRAM
+static int DRM(_histo_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+ unsigned long slot_value = DRM_DMA_HISTOGRAM_INITIAL;
+ unsigned long prev_value = 0;
+ drm_buf_t *buffer;
+ char buf[128];
+ int error;
+
+ DRM_SYSCTL_PRINT("general statistics:\n");
+ DRM_SYSCTL_PRINT("total %10u\n", atomic_read(&dev->histo.total));
+ DRM_SYSCTL_PRINT("open %10u\n", atomic_read(&dev->total_open));
+ DRM_SYSCTL_PRINT("close %10u\n", atomic_read(&dev->total_close));
+ DRM_SYSCTL_PRINT("ioctl %10u\n", atomic_read(&dev->total_ioctl));
+ DRM_SYSCTL_PRINT("irq %10u\n", atomic_read(&dev->total_irq));
+ DRM_SYSCTL_PRINT("ctx %10u\n", atomic_read(&dev->total_ctx));
+
+ DRM_SYSCTL_PRINT("\nlock statistics:\n");
+ DRM_SYSCTL_PRINT("locks %10u\n", atomic_read(&dev->total_locks));
+ DRM_SYSCTL_PRINT("unlocks %10u\n", atomic_read(&dev->total_unlocks));
+ DRM_SYSCTL_PRINT("contends %10u\n", atomic_read(&dev->total_contends));
+ DRM_SYSCTL_PRINT("sleeps %10u\n", atomic_read(&dev->total_sleeps));
+
+
+ if (dma) {
+ DRM_SYSCTL_PRINT("\ndma statistics:\n");
+ DRM_SYSCTL_PRINT("prio %10u\n",
+ atomic_read(&dma->total_prio));
+ DRM_SYSCTL_PRINT("bytes %10u\n",
+ atomic_read(&dma->total_bytes));
+ DRM_SYSCTL_PRINT("dmas %10u\n",
+ atomic_read(&dma->total_dmas));
+ DRM_SYSCTL_PRINT("missed:\n");
+ DRM_SYSCTL_PRINT(" dma %10u\n",
+ atomic_read(&dma->total_missed_dma));
+ DRM_SYSCTL_PRINT(" lock %10u\n",
+ atomic_read(&dma->total_missed_lock));
+ DRM_SYSCTL_PRINT(" free %10u\n",
+ atomic_read(&dma->total_missed_free));
+ DRM_SYSCTL_PRINT(" sched %10u\n",
+ atomic_read(&dma->total_missed_sched));
+ DRM_SYSCTL_PRINT("tried %10u\n",
+ atomic_read(&dma->total_tried));
+ DRM_SYSCTL_PRINT("hit %10u\n",
+ atomic_read(&dma->total_hit));
+ DRM_SYSCTL_PRINT("lost %10u\n",
+ atomic_read(&dma->total_lost));
+
+ buffer = dma->next_buffer;
+ if (buffer) {
+ DRM_SYSCTL_PRINT("next_buffer %7d\n", buffer->idx);
+ } else {
+ DRM_SYSCTL_PRINT("next_buffer none\n");
+ }
+ buffer = dma->this_buffer;
+ if (buffer) {
+ DRM_SYSCTL_PRINT("this_buffer %7d\n", buffer->idx);
+ } else {
+ DRM_SYSCTL_PRINT("this_buffer none\n");
+ }
+ }
+
+
+ DRM_SYSCTL_PRINT("\nvalues:\n");
+ if (dev->lock.hw_lock) {
+ DRM_SYSCTL_PRINT("lock 0x%08x\n",
+ dev->lock.hw_lock->lock);
+ } else {
+ DRM_SYSCTL_PRINT("lock none\n");
+ }
+ DRM_SYSCTL_PRINT("context_flag 0x%08x\n", dev->context_flag);
+ DRM_SYSCTL_PRINT("interrupt_flag 0x%08x\n", dev->interrupt_flag);
+ DRM_SYSCTL_PRINT("dma_flag 0x%08x\n", dev->dma_flag);
+
+ DRM_SYSCTL_PRINT("queue_count %10d\n", dev->queue_count);
+ DRM_SYSCTL_PRINT("last_context %10d\n", dev->last_context);
+ DRM_SYSCTL_PRINT("last_switch %10u\n", dev->last_switch);
+ DRM_SYSCTL_PRINT("last_checked %10d\n", dev->last_checked);
+
+
+ DRM_SYSCTL_PRINT("\n q2d d2c c2f"
+ " q2c q2f dma sch"
+ " ctx lacq lhld\n\n");
+ for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) {
+ DRM_SYSCTL_PRINT("%s %10lu %10u %10u %10u %10u %10u"
+ " %10u %10u %10u %10u %10u\n",
+ i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ",
+ i == DRM_DMA_HISTOGRAM_SLOTS - 1
+ ? prev_value : slot_value ,
+
+ atomic_read(&dev->histo
+ .queued_to_dispatched[i]),
+ atomic_read(&dev->histo
+ .dispatched_to_completed[i]),
+ atomic_read(&dev->histo
+ .completed_to_freed[i]),
+
+ atomic_read(&dev->histo
+ .queued_to_completed[i]),
+ atomic_read(&dev->histo
+ .queued_to_freed[i]),
+ atomic_read(&dev->histo.dma[i]),
+ atomic_read(&dev->histo.schedule[i]),
+ atomic_read(&dev->histo.ctx[i]),
+ atomic_read(&dev->histo.lacq[i]),
+ atomic_read(&dev->histo.lhld[i]));
+ prev_value = slot_value;
+ slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value);
+ }
+ SYSCTL_OUT(req, "", 1);
+ return 0;
+}
+
+static int DRM(histo_info)DRM_SYSCTL_HANDLER_ARGS
+{
+ drm_device_t *dev = arg1;
+ int ret;
+
+ DRM_OS_LOCK;
+ ret = _drm_histo_info(oidp, arg1, arg2, req);
+ DRM_OS_UNLOCK;
+ return ret;
+}
+#endif
diff --git a/sys/dev/drm/drm_vm.h b/sys/dev/drm/drm_vm.h
new file mode 100644
index 0000000..1e9a7c5
--- /dev/null
+++ b/sys/dev/drm/drm_vm.h
@@ -0,0 +1,85 @@
+/*
+ * $FreeBSD$
+ */
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+static int DRM(dma_mmap)(dev_t kdev, vm_offset_t offset, int prot)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ drm_device_dma_t *dma = dev->dma;
+ unsigned long physical;
+ unsigned long page;
+
+ if (!dma) return -1; /* Error */
+ if (!dma->pagelist) return -1; /* Nothing allocated */
+
+ page = offset >> PAGE_SHIFT;
+ physical = dma->pagelist[page];
+
+ DRM_DEBUG("0x%08x (page %lu) => 0x%08lx\n", offset, page, physical);
+ return atop(physical);
+}
+
+int DRM(mmap)(dev_t kdev, vm_offset_t offset, int prot)
+{
+ drm_device_t *dev = kdev->si_drv1;
+ drm_map_t *map = NULL;
+ drm_map_list_entry_t *listentry=NULL;
+ /*drm_file_t *priv;*/
+
+/* DRM_DEBUG("offset = 0x%x\n", offset);*/
+
+ /*XXX Fixme */
+ /*priv = DRM(find_file_by_proc)(dev, p);
+ if (!priv) {
+ DRM_DEBUG("can't find authenticator\n");
+ return EINVAL;
+ }
+
+ if (!priv->authenticated) DRM_OS_RETURN(EACCES);*/
+
+ if (dev->dma
+ && offset >= 0
+ && offset < ptoa(dev->dma->page_count))
+ return DRM(dma_mmap)(kdev, offset, prot);
+
+ /* 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. */
+ TAILQ_FOREACH(listentry, dev->maplist, link) {
+ map = listentry->map;
+/* DRM_DEBUG("considering 0x%x..0x%x\n", map->offset, map->offset + map->size - 1);*/
+ if (offset >= map->offset
+ && offset < map->offset + map->size) break;
+ }
+
+ if (!listentry) {
+ DRM_DEBUG("can't find map\n");
+ return -1;
+ }
+ if (((map->flags&_DRM_RESTRICTED) && suser(DRM_OS_CURPROC))) {
+ DRM_DEBUG("restricted map\n");
+ return -1;
+ }
+
+ switch (map->type) {
+ case _DRM_FRAME_BUFFER:
+ case _DRM_REGISTERS:
+ case _DRM_AGP:
+ return atop(offset);
+ case _DRM_SHM:
+ return atop(vtophys(offset));
+ default:
+ return -1; /* This should never happen. */
+ }
+ DRM_DEBUG("bailing out\n");
+
+ return -1;
+}
+
diff --git a/sys/dev/drm/gamma.h b/sys/dev/drm/gamma.h
new file mode 100644
index 0000000..222fd11
--- /dev/null
+++ b/sys/dev/drm/gamma.h
@@ -0,0 +1,95 @@
+/* gamma.c -- 3dlabs GMX 2000 driver -*- linux-c -*-
+ * Created: Mon Jan 4 08:58:31 1999 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __GAMMA_H__
+#define __GAMMA_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) gamma_##x
+
+/* General customization:
+ */
+#define __HAVE_MTRR 1
+
+/* DMA customization:
+ */
+#define __HAVE_DMA 1
+#define __HAVE_OLD_DMA 1
+#define __HAVE_PCI_DMA 1
+
+#define __HAVE_MULTIPLE_DMA_QUEUES 1
+#define __HAVE_DMA_WAITQUEUE 1
+
+#define __HAVE_DMA_WAITLIST 1
+#define __HAVE_DMA_FREELIST 1
+
+#define __HAVE_DMA_FLUSH 1
+#define __HAVE_DMA_SCHEDULE 1
+
+#define __HAVE_DMA_READY 1
+#define DRIVER_DMA_READY() do { \
+ gamma_dma_ready(dev); \
+} while (0)
+
+#define __HAVE_DMA_QUIESCENT 1
+#define DRIVER_DMA_QUIESCENT() do { \
+ /* FIXME ! */ \
+ gamma_dma_quiescent_dual(dev); \
+ return 0; \
+} while (0)
+
+#define __HAVE_DMA_IRQ 1
+#define __HAVE_DMA_IRQ_BH 1
+#define DRIVER_PREINSTALL() do { \
+ drm_gamma_private_t *dev_priv = \
+ (drm_gamma_private_t *)dev->dev_private;\
+ GAMMA_WRITE( GAMMA_GCOMMANDMODE, 0x00000000 ); \
+ GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 ); \
+} while (0)
+
+#define DRIVER_POSTINSTALL() do { \
+ drm_gamma_private_t *dev_priv = \
+ (drm_gamma_private_t *)dev->dev_private;\
+ GAMMA_WRITE( GAMMA_GINTENABLE, 0x00002001 ); \
+ GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000008 ); \
+ GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00039090 ); \
+} while (0)
+
+#define DRIVER_UNINSTALL() do { \
+ drm_gamma_private_t *dev_priv = \
+ (drm_gamma_private_t *)dev->dev_private;\
+ GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00000000 ); \
+ GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 ); \
+ GAMMA_WRITE( GAMMA_GINTENABLE, 0x00000000 ); \
+} while (0)
+
+#endif /* __GAMMA_H__ */
diff --git a/sys/dev/drm/gamma_dma.c b/sys/dev/drm/gamma_dma.c
new file mode 100644
index 0000000..df7f13d
--- /dev/null
+++ b/sys/dev/drm/gamma_dma.c
@@ -0,0 +1,647 @@
+/* gamma_dma.c -- DMA support for GMX 2000 -*- linux-c -*-
+ * Created: Fri Mar 19 14:30:16 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>
+ *
+ * $FreeBSD$
+ */
+
+
+#ifdef __linux__
+#define __NO_VERSION__
+#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
+#endif /* __linux__ */
+
+#include "dev/drm/gamma.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/gamma_drv.h"
+
+
+static __inline__ void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
+ unsigned long length)
+{
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+
+ GAMMA_WRITE(GAMMA_DMAADDRESS, DRM_OS_VTOPHYS((void *)address));
+ while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
+ ;
+ GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
+}
+
+void gamma_dma_quiescent_single(drm_device_t *dev)
+{
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+
+ while (GAMMA_READ(GAMMA_DMACOUNT))
+ ;
+ while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
+ ;
+
+ GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
+ GAMMA_WRITE(GAMMA_SYNC, 0);
+
+ do {
+ while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
+ ;
+ } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
+}
+
+void gamma_dma_quiescent_dual(drm_device_t *dev)
+{
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+
+ while (GAMMA_READ(GAMMA_DMACOUNT))
+ ;
+ while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
+ ;
+
+ GAMMA_WRITE(GAMMA_BROADCASTMASK, 3);
+
+ GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
+ GAMMA_WRITE(GAMMA_SYNC, 0);
+
+ /* Read from first MX */
+ do {
+ while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
+ ;
+ } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
+
+ /* Read from second MX */
+ do {
+ while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
+ ;
+ } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
+}
+
+void gamma_dma_ready(drm_device_t *dev)
+{
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+
+ while (GAMMA_READ(GAMMA_DMACOUNT))
+ ;
+}
+
+static __inline__ int gamma_dma_is_ready(drm_device_t *dev)
+{
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+
+ return !GAMMA_READ(GAMMA_DMACOUNT);
+}
+
+void gamma_dma_service( DRM_OS_IRQ_ARGS)
+{
+ drm_device_t *dev = (drm_device_t *)device;
+ drm_device_dma_t *dma = dev->dma;
+ drm_gamma_private_t *dev_priv =
+ (drm_gamma_private_t *)dev->dev_private;
+
+ atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
+ GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
+ GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
+ GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
+ if (gamma_dma_is_ready(dev)) {
+ /* Free previous buffer */
+ if (test_and_set_bit(0, &dev->dma_flag)) return;
+ if (dma->this_buffer) {
+ gamma_free_buffer(dev, dma->this_buffer);
+ dma->this_buffer = NULL;
+ }
+ clear_bit(0, &dev->dma_flag);
+
+#ifdef __linux__
+ /* XXX: Does FreeBSD need something here?*/
+ /* Dispatch new buffer */
+ queue_task(&dev->tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+#endif /* __linux__ */
+ }
+}
+
+/* Only called by gamma_dma_schedule. */
+static int gamma_do_dma(drm_device_t *dev, int locked)
+{
+ unsigned long address;
+ unsigned long length;
+ drm_buf_t *buf;
+ int retcode = 0;
+ drm_device_dma_t *dma = dev->dma;
+#if DRM_DMA_HISTOGRAM
+ cycles_t dma_start, dma_stop;
+#endif
+
+ if (test_and_set_bit(0, &dev->dma_flag)) DRM_OS_RETURN( EBUSY );
+
+#if DRM_DMA_HISTOGRAM
+ dma_start = get_cycles();
+#endif
+
+ if (!dma->next_buffer) {
+ DRM_ERROR("No next_buffer\n");
+ clear_bit(0, &dev->dma_flag);
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ buf = dma->next_buffer;
+ address = (unsigned long)buf->address;
+ length = buf->used;
+
+ DRM_DEBUG("context %d, buffer %d (%ld bytes)\n",
+ buf->context, buf->idx, length);
+
+ if (buf->list == DRM_LIST_RECLAIM) {
+ gamma_clear_next_buffer(dev);
+ gamma_free_buffer(dev, buf);
+ clear_bit(0, &dev->dma_flag);
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ if (!length) {
+ DRM_ERROR("0 length buffer\n");
+ gamma_clear_next_buffer(dev);
+ gamma_free_buffer(dev, buf);
+ clear_bit(0, &dev->dma_flag);
+ return 0;
+ }
+
+ if (!gamma_dma_is_ready(dev)) {
+ clear_bit(0, &dev->dma_flag);
+ DRM_OS_RETURN( EBUSY );
+ }
+
+ if (buf->while_locked) {
+ if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("Dispatching buffer %d from pid %d"
+ " \"while locked\", but no lock held\n",
+ buf->idx, buf->pid);
+ }
+ } else {
+ if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ clear_bit(0, &dev->dma_flag);
+ DRM_OS_RETURN( EBUSY );
+ }
+ }
+
+ if (dev->last_context != buf->context
+ && !(dev->queuelist[buf->context]->flags
+ & _DRM_CONTEXT_PRESERVED)) {
+ /* PRE: dev->last_context != buf->context */
+ if (DRM(context_switch)(dev, dev->last_context,
+ buf->context)) {
+ DRM(clear_next_buffer)(dev);
+ DRM(free_buffer)(dev, buf);
+ }
+ retcode = EBUSY;
+ goto cleanup;
+
+ /* POST: we will wait for the context
+ switch and will dispatch on a later call
+ when dev->last_context == buf->context.
+ NOTE WE HOLD THE LOCK THROUGHOUT THIS
+ TIME! */
+ }
+
+ gamma_clear_next_buffer(dev);
+ buf->pending = 1;
+ buf->waiting = 0;
+ buf->list = DRM_LIST_PEND;
+#if DRM_DMA_HISTOGRAM
+ buf->time_dispatched = get_cycles();
+#endif
+
+ gamma_dma_dispatch(dev, address, length);
+ gamma_free_buffer(dev, dma->this_buffer);
+ dma->this_buffer = buf;
+
+ atomic_inc(&dev->counts[7]); /* _DRM_STAT_DMA */
+ atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
+
+ if (!buf->while_locked && !dev->context_flag && !locked) {
+ if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ DRM_ERROR("\n");
+ }
+ }
+cleanup:
+
+ clear_bit(0, &dev->dma_flag);
+
+#if DRM_DMA_HISTOGRAM
+ dma_stop = get_cycles();
+ atomic_inc(&dev->histo.dma[gamma_histogram_slot(dma_stop - dma_start)]);
+#endif
+
+ DRM_OS_RETURN( retcode );
+}
+
+static void gamma_dma_timer_bh(unsigned long dev)
+{
+ gamma_dma_schedule((drm_device_t *)dev, 0);
+}
+
+void gamma_dma_immediate_bh(DRM_OS_TASKQUEUE_ARGS)
+{
+ gamma_dma_schedule(dev, 0);
+}
+
+int gamma_dma_schedule(drm_device_t *dev, int locked)
+{
+ int next;
+ drm_queue_t *q;
+ drm_buf_t *buf;
+ int retcode = 0;
+ int processed = 0;
+ int missed;
+ int expire = 20;
+ drm_device_dma_t *dma = dev->dma;
+#if DRM_DMA_HISTOGRAM
+ cycles_t schedule_start;
+#endif
+
+ if (test_and_set_bit(0, &dev->interrupt_flag)) {
+ /* Not reentrant */
+ atomic_inc(&dev->counts[10]); /* _DRM_STAT_MISSED */
+ DRM_OS_RETURN( EBUSY );
+ }
+ missed = atomic_read(&dev->counts[10]);
+
+#if DRM_DMA_HISTOGRAM
+ schedule_start = get_cycles();
+#endif
+
+again:
+ if (dev->context_flag) {
+ clear_bit(0, &dev->interrupt_flag);
+ DRM_OS_RETURN( EBUSY );
+ }
+ if (dma->next_buffer) {
+ /* Unsent buffer that was previously
+ selected, but that couldn't be sent
+ because the lock could not be obtained
+ or the DMA engine wasn't ready. Try
+ again. */
+ if (!(retcode = gamma_do_dma(dev, locked))) ++processed;
+ } else {
+ do {
+ next = gamma_select_queue(dev, gamma_dma_timer_bh);
+ if (next >= 0) {
+ q = dev->queuelist[next];
+ buf = gamma_waitlist_get(&q->waitlist);
+ dma->next_buffer = buf;
+ dma->next_queue = q;
+ if (buf && buf->list == DRM_LIST_RECLAIM) {
+ gamma_clear_next_buffer(dev);
+ gamma_free_buffer(dev, buf);
+ }
+ }
+ } while (next >= 0 && !dma->next_buffer);
+ if (dma->next_buffer) {
+ if (!(retcode = gamma_do_dma(dev, locked))) {
+ ++processed;
+ }
+ }
+ }
+
+ if (--expire) {
+ if (missed != atomic_read(&dev->counts[10])) {
+ if (gamma_dma_is_ready(dev)) goto again;
+ }
+ if (processed && gamma_dma_is_ready(dev)) {
+ processed = 0;
+ goto again;
+ }
+ }
+
+ clear_bit(0, &dev->interrupt_flag);
+
+#if DRM_DMA_HISTOGRAM
+ atomic_inc(&dev->histo.schedule[gamma_histogram_slot(get_cycles()
+ - schedule_start)]);
+#endif
+ return retcode;
+}
+
+static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d)
+{
+ unsigned long address;
+ unsigned long length;
+ int must_free = 0;
+ int retcode = 0;
+ int i;
+ int idx;
+ drm_buf_t *buf;
+ drm_buf_t *last_buf = NULL;
+ drm_device_dma_t *dma = dev->dma;
+#ifdef __linux__
+ DECLARE_WAITQUEUE(entry, current);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ static int never;
+#endif /* __FreeBSD__ */
+
+ /* Turn off interrupt handling */
+ while (test_and_set_bit(0, &dev->interrupt_flag)) {
+#ifdef __linux__
+ schedule();
+ if (signal_pending(current)) return -EINTR;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ retcode = tsleep(&never, PZERO|PCATCH, "gamp1", 1);
+ if (retcode)
+ return retcode;
+#endif /* __FreeBSD__ */
+ }
+ if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
+ while (!gamma_lock_take(&dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+#ifdef __linux__
+ schedule();
+ if (signal_pending(current)) {
+ clear_bit(0, &dev->interrupt_flag);
+ return -EINTR;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ retcode = tsleep(&never, PZERO|PCATCH, "gamp2", 1);
+ if (retcode)
+ return retcode;
+#endif /* __FreeBSD__ */
+ }
+ ++must_free;
+ }
+
+ for (i = 0; i < d->send_count; i++) {
+ idx = d->send_indices[i];
+ if (idx < 0 || idx >= dma->buf_count) {
+ DRM_ERROR("Index %d (of %d max)\n",
+ d->send_indices[i], dma->buf_count - 1);
+ continue;
+ }
+ buf = dma->buflist[ idx ];
+ if (buf->pid != DRM_OS_CURRENTPID) {
+ DRM_ERROR("Process %d using buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid);
+ retcode = EINVAL;
+ goto cleanup;
+ }
+ if (buf->list != DRM_LIST_NONE) {
+ DRM_ERROR("Process %d using %d's buffer on list %d\n",
+ DRM_OS_CURRENTPID, buf->pid, buf->list);
+ retcode = EINVAL;
+ goto cleanup;
+ }
+ /* This isn't a race condition on
+ buf->list, since our concern is the
+ buffer reclaim during the time the
+ process closes the /dev/drm? handle, so
+ it can't also be doing DMA. */
+ buf->list = DRM_LIST_PRIO;
+ buf->used = d->send_sizes[i];
+ buf->context = d->context;
+ buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED;
+ address = (unsigned long)buf->address;
+ length = buf->used;
+ if (!length) {
+ DRM_ERROR("0 length buffer\n");
+ }
+ if (buf->pending) {
+ DRM_ERROR("Sending pending buffer:"
+ " buffer %d, offset %d\n",
+ d->send_indices[i], i);
+ retcode = EINVAL;
+ goto cleanup;
+ }
+ if (buf->waiting) {
+ DRM_ERROR("Sending waiting buffer:"
+ " buffer %d, offset %d\n",
+ d->send_indices[i], i);
+ retcode = EINVAL;
+ goto cleanup;
+ }
+ buf->pending = 1;
+
+ if (dev->last_context != buf->context
+ && !(dev->queuelist[buf->context]->flags
+ & _DRM_CONTEXT_PRESERVED)) {
+#ifdef __linux__
+ add_wait_queue(&dev->context_wait, &entry);
+ current->state = TASK_INTERRUPTIBLE;
+#endif /* __linux__ */
+ /* PRE: dev->last_context != buf->context */
+ DRM(context_switch)(dev, dev->last_context,
+ buf->context);
+ /* POST: we will wait for the context
+ switch and will dispatch on a later call
+ when dev->last_context == buf->context.
+ NOTE WE HOLD THE LOCK THROUGHOUT THIS
+ TIME! */
+#ifdef __linux__
+ schedule();
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&dev->context_wait, &entry);
+ if (signal_pending(current)) {
+ retcode = EINTR;
+ goto cleanup;
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ retcode = tsleep(&dev->context_wait, PZERO|PCATCH,
+ "gamctx", 0);
+ if (retcode)
+ goto cleanup;
+#endif /* __FreeBSD__ */
+ if (dev->last_context != buf->context) {
+ DRM_ERROR("Context mismatch: %d %d\n",
+ dev->last_context,
+ buf->context);
+ }
+ }
+
+#if DRM_DMA_HISTOGRAM
+ buf->time_queued = get_cycles();
+ buf->time_dispatched = buf->time_queued;
+#endif
+ gamma_dma_dispatch(dev, address, length);
+ atomic_inc(&dev->counts[9]); /* _DRM_STAT_SPECIAL */
+ atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
+
+ if (last_buf) {
+ gamma_free_buffer(dev, last_buf);
+ }
+ last_buf = buf;
+ }
+
+
+cleanup:
+ if (last_buf) {
+ gamma_dma_ready(dev);
+ gamma_free_buffer(dev, last_buf);
+ }
+
+ if (must_free && !dev->context_flag) {
+ if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ DRM_ERROR("\n");
+ }
+ }
+ clear_bit(0, &dev->interrupt_flag);
+ DRM_OS_RETURN( retcode );
+}
+
+static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
+{
+ drm_buf_t *last_buf = NULL;
+ int retcode = 0;
+ drm_device_dma_t *dma = dev->dma;
+#ifdef __linux__
+ DECLARE_WAITQUEUE(entry, current);
+#endif /* __linux__ */
+
+ if (d->flags & _DRM_DMA_BLOCK) {
+ last_buf = dma->buflist[d->send_indices[d->send_count-1]];
+#ifdef __linux__
+ add_wait_queue(&last_buf->dma_wait, &entry);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ atomic_inc(&last_buf->dma_wait);
+#endif /* __FreeBSD__ */
+ }
+
+ if ((retcode = gamma_dma_enqueue(dev, d))) {
+ if (d->flags & _DRM_DMA_BLOCK)
+#ifdef __linux__
+ remove_wait_queue(&last_buf->dma_wait, &entry);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ atomic_dec(&last_buf->dma_wait);
+#endif /* __FreeBSD__ */
+ return retcode;
+ }
+
+ gamma_dma_schedule(dev, 0);
+
+ if (d->flags & _DRM_DMA_BLOCK) {
+ DRM_DEBUG("%d waiting\n", DRM_OS_CURRENTPID);
+#ifdef __linux__
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ if (!last_buf->waiting && !last_buf->pending)
+ break; /* finished */
+ schedule();
+ if (signal_pending(current)) {
+ retcode = EINTR; /* Can't restart */
+ break;
+ }
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&last_buf->dma_wait, &entry);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ for (;;) {
+ retcode = tsleep(&last_buf->dma_wait, PZERO|PCATCH,
+ "gamdw", 0);
+ if (!last_buf->waiting
+ && !last_buf->pending)
+ break; /* finished */
+ if (retcode)
+ break;
+ }
+ atomic_dec(&last_buf->dma_wait);
+#endif /* __FreeBSD__ */
+ DRM_DEBUG("%d running\n", DRM_OS_CURRENTPID);
+ if (!retcode
+ || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
+#ifdef __linux__
+ if (!waitqueue_active(&last_buf->dma_wait)) {
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if (!last_buf->dma_wait) {
+#endif /* __FreeBSD__ */
+ gamma_free_buffer(dev, last_buf);
+ }
+ }
+ if (retcode) {
+ DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%d\n",
+ d->context,
+ last_buf->waiting,
+ last_buf->pending,
+ DRM_WAITCOUNT(dev, d->context),
+ last_buf->idx,
+ last_buf->list,
+ last_buf->pid,
+ DRM_OS_CURRENTPID);
+ }
+ }
+ DRM_OS_RETURN( retcode );
+}
+
+int gamma_dma( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ int retcode = 0;
+ drm_dma_t d;
+
+ DRM_OS_KRNFROMUSR(d, (drm_dma_t *) data, sizeof(d));
+
+ if (d.send_count < 0 || d.send_count > dma->buf_count) {
+ DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
+ DRM_OS_CURRENTPID, d.send_count, dma->buf_count);
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ 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_OS_CURRENTPID, d.request_count, dma->buf_count);
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ if (d.send_count) {
+ if (d.flags & _DRM_DMA_PRIORITY)
+ retcode = gamma_dma_priority(dev, &d);
+ else
+ retcode = gamma_dma_send_buffers(dev, &d);
+ }
+
+ d.granted_count = 0;
+
+ if (!retcode && d.request_count) {
+ retcode = gamma_dma_get_buffers(dev, &d);
+ }
+
+ DRM_DEBUG("%d returning, granted = %d\n",
+ DRM_OS_CURRENTPID, d.granted_count);
+ DRM_OS_KRNTOUSR((drm_dma_t *) data, d, sizeof(d));
+
+ return retcode;
+}
diff --git a/sys/dev/drm/gamma_drv.c b/sys/dev/drm/gamma_drv.c
new file mode 100644
index 0000000..7defc26
--- /dev/null
+++ b/sys/dev/drm/gamma_drv.c
@@ -0,0 +1,125 @@
+/* gamma.c -- 3dlabs GMX 2000 driver -*- linux-c -*-
+ * Created: Mon Jan 4 08:58:31 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>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __linux__
+#include <linux/config.h>
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <pci/pcivar.h>
+#include <opt_drm_linux.h>
+#endif /* __FreeBSD__ */
+#include "dev/drm/gamma.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/gamma_drv.h"
+
+#define DRIVER_AUTHOR "VA Linux Systems Inc."
+
+#define DRIVER_NAME "gamma"
+#define DRIVER_DESC "3DLabs gamma"
+#define DRIVER_DATE "20010216"
+
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+#define DRIVER_IOCTLS \
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { gamma_dma, 1, 0 }
+
+#ifdef __FreeBSD__
+/* List acquired from xc/xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h
+ * Please report to eanholt@gladstone.uoregon.edu if your chip isn't
+ * represented in the list or if the information is incorrect.
+ */
+drm_chipinfo_t DRM(devicelist)[] = {
+ {0x3d3d, 0x0008, 1, "3DLabs Gamma"},
+ {0, 0, 0, NULL}
+};
+#endif /* __FreeBSD__ */
+
+
+#define __HAVE_COUNTERS 5
+#define __HAVE_COUNTER6 _DRM_STAT_IRQ
+#define __HAVE_COUNTER7 _DRM_STAT_DMA
+#define __HAVE_COUNTER8 _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER9 _DRM_STAT_SPECIAL
+#define __HAVE_COUNTER10 _DRM_STAT_MISSED
+
+
+#include "dev/drm/drm_auth.h"
+#include "dev/drm/drm_bufs.h"
+#include "dev/drm/drm_context.h"
+#include "dev/drm/drm_dma.h"
+#include "dev/drm/drm_drawable.h"
+#include "dev/drm/drm_drv.h"
+
+#ifdef __linux__
+#ifndef MODULE
+/* DRM(options) is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO). It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+
+/* JH- We have to hand expand the string ourselves because of the cpp. If
+ * anyone can think of a way that we can fit into the __setup macro without
+ * changing it, then please send the solution my way.
+ */
+static int __init gamma_options( char *str )
+{
+ DRM(parse_options)( str );
+ return 1;
+}
+
+__setup( DRIVER_NAME "=", gamma_options );
+#endif
+#endif /* __linux__ */
+
+#include "dev/drm/drm_fops.h"
+#include "dev/drm/drm_init.h"
+#include "dev/drm/drm_ioctl.h"
+#include "dev/drm/drm_lists.h"
+#include "dev/drm/drm_lock.h"
+#include "dev/drm/drm_memory.h"
+#ifdef __linux__
+#include "dev/drm/drm_proc.h"
+#endif /* __linux__ */
+#include "dev/drm/drm_vm.h"
+#ifdef __linux__
+#include "dev/drm/drm_stub.h"
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include "dev/drm/drm_sysctl.h"
+
+DRIVER_MODULE(gamma, pci, gamma_driver, gamma_devclass, 0, 0);
+#endif /* __FreeBSD__ */
diff --git a/sys/dev/drm/gamma_drv.h b/sys/dev/drm/gamma_drv.h
new file mode 100644
index 0000000..5ee3e37
--- /dev/null
+++ b/sys/dev/drm/gamma_drv.h
@@ -0,0 +1,105 @@
+/* gamma_drv.h -- Private header for 3dlabs GMX 2000 driver -*- linux-c -*-
+ * Created: Mon Jan 4 10:05:05 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _GAMMA_DRV_H_
+#define _GAMMA_DRV_H_
+
+
+typedef struct drm_gamma_private {
+ drm_map_t *buffers;
+ drm_map_t *mmio0;
+ drm_map_t *mmio1;
+ drm_map_t *mmio2;
+ drm_map_t *mmio3;
+} drm_gamma_private_t;
+
+#define LOCK_TEST_WITH_RETURN( dev ) \
+do { \
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
+ dev->lock.pid != DRM_OS_CURRENTPID ) { \
+ DRM_ERROR( "%s called without lock held\n", \
+ __FUNCTION__ ); \
+ DRM_OS_RETURN( EINVAL ); \
+ } \
+} while (0)
+
+
+extern void gamma_dma_ready(drm_device_t *dev);
+extern void gamma_dma_quiescent_single(drm_device_t *dev);
+extern void gamma_dma_quiescent_dual(drm_device_t *dev);
+
+ /* gamma_dma.c */
+extern int gamma_dma_schedule(drm_device_t *dev, int locked);
+extern int gamma_dma( DRM_OS_IOCTL );
+extern int gamma_find_devices(void);
+extern int gamma_found(void);
+
+
+#define GAMMA_OFF(reg) \
+ ((reg < 0x1000) \
+ ? reg \
+ : ((reg < 0x10000) \
+ ? (reg - 0x1000) \
+ : ((reg < 0x11000) \
+ ? (reg - 0x10000) \
+ : (reg - 0x11000))))
+
+#define GAMMA_BASE(reg) ((unsigned long) \
+ ((reg < 0x1000) ? dev_priv->mmio0->handle : \
+ ((reg < 0x10000) ? dev_priv->mmio1->handle : \
+ ((reg < 0x11000) ? dev_priv->mmio2->handle : \
+ dev_priv->mmio3->handle))))
+
+#define GAMMA_ADDR(reg) (GAMMA_BASE(reg) + GAMMA_OFF(reg))
+#define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
+#define GAMMA_READ(reg) GAMMA_DEREF(reg)
+#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
+
+#define GAMMA_BROADCASTMASK 0x9378
+#define GAMMA_COMMANDINTENABLE 0x0c48
+#define GAMMA_DMAADDRESS 0x0028
+#define GAMMA_DMACOUNT 0x0030
+#define GAMMA_FILTERMODE 0x8c00
+#define GAMMA_GCOMMANDINTFLAGS 0x0c50
+#define GAMMA_GCOMMANDMODE 0x0c40
+#define GAMMA_GCOMMANDSTATUS 0x0c60
+#define GAMMA_GDELAYTIMER 0x0c38
+#define GAMMA_GDMACONTROL 0x0060
+#define GAMMA_GINTENABLE 0x0808
+#define GAMMA_GINTFLAGS 0x0810
+#define GAMMA_INFIFOSPACE 0x0018
+#define GAMMA_OUTFIFOWORDS 0x0020
+#define GAMMA_OUTPUTFIFO 0x2000
+#define GAMMA_SYNC 0x8c40
+#define GAMMA_SYNC_TAG 0x0188
+
+#endif
diff --git a/sys/dev/drm/i810_drm.h b/sys/dev/drm/i810_drm.h
new file mode 100644
index 0000000..4a26b74
--- /dev/null
+++ b/sys/dev/drm/i810_drm.h
@@ -0,0 +1,203 @@
+/*
+ * $FreeBSD$
+ */
+
+#ifndef _I810_DRM_H_
+#define _I810_DRM_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ */
+
+#ifndef _I810_DEFINES_
+#define _I810_DEFINES_
+
+#define I810_DMA_BUF_ORDER 12
+#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER)
+#define I810_DMA_BUF_NR 256
+#define I810_NR_SAREA_CLIPRECTS 8
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define I810_NR_TEX_REGIONS 64
+#define I810_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
+#define I810_UPLOAD_CTX 0x4
+#define I810_UPLOAD_BUFFERS 0x8
+#define I810_UPLOAD_TEX0 0x10
+#define I810_UPLOAD_TEX1 0x20
+#define I810_UPLOAD_CLIPRECTS 0x40
+
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer. These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* Destbuffer state
+ * - backbuffer linear offset and pitch -- invarient in the current dri
+ * - zbuffer linear offset and pitch -- also invarient
+ * - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to acommodate private buffers
+ * in the future.
+ */
+#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
+#define I810_DESTREG_DI1 1
+#define I810_DESTREG_DV0 2 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
+#define I810_DESTREG_DV1 3
+#define I810_DESTREG_DR0 4 /* GFX_OP_DRAWRECT_INFO (4 dwords) */
+#define I810_DESTREG_DR1 5
+#define I810_DESTREG_DR2 6
+#define I810_DESTREG_DR3 7
+#define I810_DESTREG_DR4 8
+#define I810_DEST_SETUP_SIZE 10
+
+/* Context state
+ */
+#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */
+#define I810_CTXREG_CF1 1
+#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */
+#define I810_CTXREG_ST1 3
+#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */
+#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */
+#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
+#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
+#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
+#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
+#define I810_CTXREG_MA2 11 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
+#define I810_CTXREG_SDM 12 /* GFX_OP_SRC_DEST_MONO */
+#define I810_CTXREG_FOG 13 /* GFX_OP_FOG_COLOR */
+#define I810_CTXREG_B1 14 /* GFX_OP_BOOL_1 */
+#define I810_CTXREG_B2 15 /* GFX_OP_BOOL_2 */
+#define I810_CTXREG_LCS 16 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
+#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */
+#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */
+#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */
+#define I810_CTX_SETUP_SIZE 20
+
+/* Texture state (per tex unit)
+ */
+#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */
+#define I810_TEXREG_MI1 1
+#define I810_TEXREG_MI2 2
+#define I810_TEXREG_MI3 3
+#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */
+#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */
+#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */
+#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */
+#define I810_TEX_SETUP_SIZE 8
+
+#define I810_FRONT 0x1
+#define I810_BACK 0x2
+#define I810_DEPTH 0x4
+
+
+typedef struct _drm_i810_init {
+ enum {
+ I810_INIT_DMA = 0x01,
+ I810_CLEANUP_DMA = 0x02
+ } func;
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
+ int ring_map_idx;
+ int buffer_map_idx;
+#else
+ unsigned int mmio_offset;
+ unsigned int buffers_offset;
+#endif
+ 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;
+} drm_i810_init_t;
+
+/* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+typedef struct _drm_i810_tex_region {
+ unsigned char next, prev; /* indices to form a circular LRU */
+ unsigned char in_use; /* owned by a client, or free? */
+ int age; /* tracked by clients to update local LRU's */
+} drm_i810_tex_region_t;
+
+typedef struct _drm_i810_sarea {
+ unsigned int ContextState[I810_CTX_SETUP_SIZE];
+ unsigned int BufferState[I810_DEST_SETUP_SIZE];
+ unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+ unsigned int dirty;
+
+ unsigned int nbox;
+ drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+
+ /* Maintain an LRU of contiguous regions of texture space. If
+ * you think you own a region of texture memory, and it has an
+ * age different to the one you set, then you are mistaken and
+ * it has been stolen by another client. If global texAge
+ * hasn't changed, there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained
+ * texture information of other clients - by maintaining them
+ * in the same lru which is used to age their own textures,
+ * clients have an approximate lru for the whole of global
+ * texture space, and can make informed decisions as to which
+ * areas to kick out. There is no need to choose whether to
+ * kick out your own texture or someone else's - simply eject
+ * them all in LRU order.
+ */
+
+ drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS+1];
+ /* Last elt is sentinal */
+ int texAge; /* last time texture was uploaded */
+ int last_enqueue; /* last time a buffer was enqueued */
+ int last_dispatch; /* age of the most recently dispatched buffer */
+ int last_quiescent; /* */
+ int ctxOwner; /* last context to upload state */
+
+ int vertex_prim;
+
+} drm_i810_sarea_t;
+
+typedef struct _drm_i810_clear {
+ int clear_color;
+ int clear_depth;
+ int flags;
+} drm_i810_clear_t;
+
+
+
+/* These may be placeholders if we have more cliprects than
+ * I810_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
+ * false, indicating that the buffer will be dispatched again with a
+ * new set of cliprects.
+ */
+typedef struct _drm_i810_vertex {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ int discard; /* client is finished with the buffer? */
+} drm_i810_vertex_t;
+
+typedef struct _drm_i810_copy_t {
+ int idx; /* buffer index */
+ int used; /* nr bytes in use */
+ void *address; /* Address to copy from */
+} drm_i810_copy_t;
+
+typedef struct drm_i810_dma {
+ void *virtual;
+ int request_idx;
+ int request_size;
+ int granted;
+} drm_i810_dma_t;
+
+#endif /* _I810_DRM_H_ */
diff --git a/sys/dev/drm/mga.h b/sys/dev/drm/mga.h
new file mode 100644
index 0000000..a469c09
--- /dev/null
+++ b/sys/dev/drm/mga.h
@@ -0,0 +1,69 @@
+/* mga.h -- Matrox G200/G400 DRM template customization -*- 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MGA_H__
+#define __MGA_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) mga_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP 1
+#define __MUST_HAVE_AGP 1
+#define __HAVE_MTRR 1
+#define __HAVE_CTX_BITMAP 1
+
+/* Driver customization:
+ */
+#define DRIVER_PRETAKEDOWN() do { \
+ if ( dev->dev_private ) mga_do_cleanup_dma( dev ); \
+} while (0)
+
+/* DMA customization:
+ */
+#define __HAVE_DMA 1
+
+#define __HAVE_DMA_QUIESCENT 1
+#define DRIVER_DMA_QUIESCENT() do { \
+ drm_mga_private_t *dev_priv = dev->dev_private; \
+ return mga_do_wait_for_idle( dev_priv ); \
+} while (0)
+
+/* Buffer customization:
+ */
+#define DRIVER_BUF_PRIV_T drm_mga_buf_priv_t
+
+#define DRIVER_AGP_BUFFERS_MAP( dev ) \
+ ((drm_mga_private_t *)((dev)->dev_private))->buffers
+
+#endif
diff --git a/sys/dev/drm/mga_dma.c b/sys/dev/drm/mga_dma.c
new file mode 100644
index 0000000..8c5d233
--- /dev/null
+++ b/sys/dev/drm/mga_dma.c
@@ -0,0 +1,851 @@
+/* mga_dma.c -- DMA support for mga g200/g400 -*- 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
+ * 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>
+ * Jeff Hartmann <jhartmann@valinux.com>
+ * Keith Whitwell <keithw@valinux.com>
+ *
+ * Rewritten by:
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/mga.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/mga_drv.h"
+
+#ifdef __linux__
+#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
+#endif /* __linux__ */
+
+#define MGA_DEFAULT_USEC_TIMEOUT 10000
+#define MGA_FREELIST_DEBUG 0
+
+
+/* ================================================================
+ * Engine control
+ */
+
+int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
+{
+ u32 status = 0;
+ int i;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
+ if ( status == MGA_ENDPRDMASTS ) {
+ MGA_WRITE8( MGA_CRTC_INDEX, 0 );
+ return 0;
+ }
+ DRM_OS_DELAY( 1 );
+ }
+
+#if MGA_DMA_DEBUG
+ DRM_ERROR( "failed!\n" );
+ DRM_INFO( " status=0x%08x\n", status );
+#endif
+ DRM_OS_RETURN(EBUSY);
+}
+
+int mga_do_dma_idle( drm_mga_private_t *dev_priv )
+{
+ u32 status = 0;
+ int i;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK;
+ if ( status == MGA_ENDPRDMASTS ) return 0;
+ DRM_OS_DELAY( 1 );
+ }
+
+#if MGA_DMA_DEBUG
+ DRM_ERROR( "failed! status=0x%08x\n", status );
+#endif
+ DRM_OS_RETURN(EBUSY);
+}
+
+int mga_do_dma_reset( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ /* The primary DMA stream should look like new right about now.
+ */
+ primary->tail = 0;
+ primary->space = primary->size;
+ primary->last_flush = 0;
+
+ sarea_priv->last_wrap = 0;
+
+ /* FIXME: Reset counters, buffer ages etc...
+ */
+
+ /* FIXME: What else do we need to reinitialize? WARP stuff?
+ */
+
+ return 0;
+}
+
+int mga_do_engine_reset( drm_mga_private_t *dev_priv )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ /* Okay, so we've completely screwed up and locked the engine.
+ * How about we clean up after ourselves?
+ */
+ MGA_WRITE( MGA_RST, MGA_SOFTRESET );
+ DRM_OS_DELAY( 15 ); /* Wait at least 10 usecs */
+ MGA_WRITE( MGA_RST, 0 );
+
+ /* Initialize the registers that get clobbered by the soft
+ * reset. Many of the core register values survive a reset,
+ * but the drawing registers are basically all gone.
+ *
+ * 3D clients should probably die after calling this. The X
+ * server should reset the engine state to known values.
+ */
+#if 0
+ MGA_WRITE( MGA_PRIMPTR,
+ virt_to_bus((void *)dev_priv->prim.status_page) |
+ MGA_PRIMPTREN0 |
+ MGA_PRIMPTREN1 );
+#endif
+
+ MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
+ MGA_WRITE( MGA_IEN, MGA_SOFTRAPIEN );
+
+ /* The primary DMA stream should look like new right about now.
+ */
+ mga_do_dma_reset( dev_priv );
+
+ /* This bad boy will never fail.
+ */
+ return 0;
+}
+
+
+/* ================================================================
+ * Primary DMA stream
+ */
+
+void mga_do_dma_flush( drm_mga_private_t *dev_priv )
+{
+ drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+ u32 head, tail;
+ DMA_LOCALS;
+ DRM_DEBUG( "%s:\n", __FUNCTION__ );
+
+ if ( primary->tail == primary->last_flush ) {
+ DRM_DEBUG( " bailing out...\n" );
+ return;
+ }
+
+ tail = primary->tail + dev_priv->primary->offset;
+
+ /* We need to pad the stream between flushes, as the card
+ * actually (partially?) reads the first of these commands.
+ * See page 4-16 in the G400 manual, middle of the page or so.
+ */
+ BEGIN_DMA( 1 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000 );
+
+ ADVANCE_DMA();
+
+ primary->last_flush = primary->tail;
+
+ head = MGA_READ( MGA_PRIMADDRESS );
+
+ if ( head <= tail ) {
+ primary->space = primary->size - primary->tail;
+ } else {
+ primary->space = head - tail;
+ }
+
+ DRM_DEBUG( " head = 0x%06lx\n", head - dev_priv->primary->offset );
+ DRM_DEBUG( " tail = 0x%06lx\n", tail - dev_priv->primary->offset );
+ DRM_DEBUG( " space = 0x%06x\n", primary->space );
+
+ mga_flush_write_combine();
+ MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+
+ DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
+}
+
+void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
+{
+ drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+ u32 head, tail;
+ DMA_LOCALS;
+ DRM_DEBUG( "%s:\n", __FUNCTION__ );
+
+ BEGIN_DMA_WRAP();
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000 );
+
+ ADVANCE_DMA();
+
+ tail = primary->tail + dev_priv->primary->offset;
+
+ primary->tail = 0;
+ primary->last_flush = 0;
+ primary->last_wrap++;
+
+ head = MGA_READ( MGA_PRIMADDRESS );
+
+ if ( head == dev_priv->primary->offset ) {
+ primary->space = primary->size;
+ } else {
+ primary->space = head - dev_priv->primary->offset;
+ }
+
+ DRM_DEBUG( " head = 0x%06lx\n",
+ head - dev_priv->primary->offset );
+ DRM_DEBUG( " tail = 0x%06x\n", primary->tail );
+ DRM_DEBUG( " wrap = %d\n", primary->last_wrap );
+ DRM_DEBUG( " space = 0x%06x\n", primary->space );
+
+ mga_flush_write_combine();
+ MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+
+ set_bit( 0, &primary->wrapped );
+ DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
+}
+
+void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
+{
+ drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ u32 head = dev_priv->primary->offset;
+ DRM_DEBUG( "%s:\n", __FUNCTION__ );
+
+ sarea_priv->last_wrap++;
+ DRM_DEBUG( " wrap = %d\n", sarea_priv->last_wrap );
+
+ mga_flush_write_combine();
+ MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
+
+ clear_bit( 0, &primary->wrapped );
+ DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
+}
+
+
+/* ================================================================
+ * Freelist management
+ */
+
+#define MGA_BUFFER_USED ~0
+#define MGA_BUFFER_FREE 0
+
+#if MGA_FREELIST_DEBUG
+static void mga_freelist_print( drm_device_t *dev )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_freelist_t *entry;
+
+ DRM_INFO( "\n" );
+ DRM_INFO( "current dispatch: last=0x%x done=0x%x\n",
+ dev_priv->sarea_priv->last_dispatch,
+ (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) -
+ dev_priv->primary->offset) );
+ DRM_INFO( "current freelist:\n" );
+
+ for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) {
+ DRM_INFO( " %p idx=%2d age=0x%x 0x%06lx\n",
+ entry, entry->buf->idx, entry->age.head,
+ entry->age.head - dev_priv->primary->offset );
+ }
+ DRM_INFO( "\n" );
+}
+#endif
+
+static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_freelist_t *entry;
+ int i;
+ DRM_DEBUG( "%s: count=%d\n",
+ __FUNCTION__, dma->buf_count );
+
+ dev_priv->head = DRM(alloc)( sizeof(drm_mga_freelist_t),
+ DRM_MEM_DRIVER );
+ if ( dev_priv->head == NULL )
+ DRM_OS_RETURN(ENOMEM);
+
+ memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) );
+ SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 );
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+
+ entry = DRM(alloc)( sizeof(drm_mga_freelist_t),
+ DRM_MEM_DRIVER );
+ if ( entry == NULL )
+ DRM_OS_RETURN(ENOMEM);
+
+ memset( entry, 0, sizeof(drm_mga_freelist_t) );
+
+ entry->next = dev_priv->head->next;
+ entry->prev = dev_priv->head;
+ SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
+ entry->buf = buf;
+
+ if ( dev_priv->head->next != NULL )
+ dev_priv->head->next->prev = entry;
+ if ( entry->next == NULL )
+ dev_priv->tail = entry;
+
+ buf_priv->list_entry = entry;
+ buf_priv->discard = 0;
+ buf_priv->dispatched = 0;
+
+ dev_priv->head->next = entry;
+ }
+
+ return 0;
+}
+
+static void mga_freelist_cleanup( drm_device_t *dev )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_freelist_t *entry;
+ drm_mga_freelist_t *next;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ entry = dev_priv->head;
+ while ( entry ) {
+ next = entry->next;
+ DRM(free)( entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER );
+ entry = next;
+ }
+
+ dev_priv->head = dev_priv->tail = NULL;
+}
+
+#if 0
+/* FIXME: Still needed?
+ */
+static void mga_freelist_reset( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ int i;
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ SET_AGE( &buf_priv->list_entry->age,
+ MGA_BUFFER_FREE, 0 );
+ }
+}
+#endif
+
+static drm_buf_t *mga_freelist_get( drm_device_t *dev )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_freelist_t *next;
+ drm_mga_freelist_t *prev;
+ drm_mga_freelist_t *tail = dev_priv->tail;
+ u32 head, wrap;
+ DRM_DEBUG( "%s:\n", __FUNCTION__ );
+
+ head = MGA_READ( MGA_PRIMADDRESS );
+ wrap = dev_priv->sarea_priv->last_wrap;
+
+ DRM_DEBUG( " tail=0x%06lx %d\n",
+ tail->age.head ?
+ tail->age.head - dev_priv->primary->offset : 0,
+ tail->age.wrap );
+ DRM_DEBUG( " head=0x%06lx %d\n",
+ head - dev_priv->primary->offset, wrap );
+
+ if ( TEST_AGE( &tail->age, head, wrap ) ) {
+ prev = dev_priv->tail->prev;
+ next = dev_priv->tail;
+ prev->next = NULL;
+ next->prev = next->next = NULL;
+ dev_priv->tail = prev;
+ SET_AGE( &next->age, MGA_BUFFER_USED, 0 );
+ return next->buf;
+ }
+
+ DRM_DEBUG( "returning NULL!\n" );
+ return NULL;
+}
+
+int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_freelist_t *head, *entry, *prev;
+
+ DRM_DEBUG( "%s: age=0x%06lx wrap=%d\n",
+ __FUNCTION__,
+ buf_priv->list_entry->age.head -
+ dev_priv->primary->offset,
+ buf_priv->list_entry->age.wrap );
+
+ entry = buf_priv->list_entry;
+ head = dev_priv->head;
+
+ if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {
+ SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
+ prev = dev_priv->tail;
+ prev->next = entry;
+ entry->prev = prev;
+ entry->next = NULL;
+ } else {
+ prev = head->next;
+ head->next = entry;
+ prev->prev = entry;
+ entry->prev = head;
+ entry->next = prev;
+ }
+
+ return 0;
+}
+
+
+/* ================================================================
+ * DMA initialization, cleanup
+ */
+
+static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
+{
+ drm_mga_private_t *dev_priv;
+#ifdef __linux__
+ struct list_head *list;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_map_list_entry_t *listentry;
+#endif /* __FreeBSD__ */
+ int ret;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
+ if ( !dev_priv )
+ DRM_OS_RETURN(ENOMEM);
+
+ memset( dev_priv, 0, sizeof(drm_mga_private_t) );
+
+ dev_priv->chipset = init->chipset;
+
+ dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
+
+ if ( init->sgram ) {
+ dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
+ } else {
+ dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
+ }
+ dev_priv->maccess = init->maccess;
+
+ dev_priv->fb_cpp = init->fb_cpp;
+ 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;
+
+ dev_priv->depth_cpp = init->depth_cpp;
+ dev_priv->depth_offset = init->depth_offset;
+ dev_priv->depth_pitch = init->depth_pitch;
+
+ /* FIXME: Need to support AGP textures...
+ */
+ dev_priv->texture_offset = init->texture_offset[0];
+ dev_priv->texture_size = init->texture_size[0];
+
+#ifdef __linux__
+ list_for_each( list, &dev->maplist->head ) {
+ drm_map_list_t *entry = (drm_map_list_t *)list;
+ if ( entry->map &&
+ entry->map->type == _DRM_SHM &&
+ (entry->map->flags & _DRM_CONTAINS_LOCK) ) {
+ dev_priv->sarea = entry->map;
+ break;
+ }
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TAILQ_FOREACH(listentry, dev->maplist, link) {
+ drm_map_t *map = listentry->map;
+ if (map->type == _DRM_SHM &&
+ map->flags & _DRM_CONTAINS_LOCK) {
+ dev_priv->sarea = map;
+ break;
+ }
+ }
+#endif /* __FreeBSD__ */
+
+ if(!dev_priv->sarea) {
+ DRM_ERROR( "failed to find sarea!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+
+ DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+ if(!dev_priv->fb) {
+ DRM_ERROR( "failed to find framebuffer!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+ if(!dev_priv->mmio) {
+ DRM_ERROR( "failed to find mmio region!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->status, init->status_offset );
+ if(!dev_priv->status) {
+ DRM_ERROR( "failed to find status page!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
+ if(!dev_priv->warp) {
+ DRM_ERROR( "failed to find warp microcode region!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
+ if(!dev_priv->primary) {
+ DRM_ERROR( "failed to find primary dma region!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+ if(!dev_priv->buffers) {
+ DRM_ERROR( "failed to find dma buffer region!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ dev_priv->sarea_priv =
+ (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ DRM_IOREMAP( dev_priv->warp );
+ DRM_IOREMAP( dev_priv->primary );
+ DRM_IOREMAP( dev_priv->buffers );
+
+ if(!dev_priv->warp->handle ||
+ !dev_priv->primary->handle ||
+ !dev_priv->buffers->handle ) {
+ DRM_ERROR( "failed to ioremap agp regions!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(ENOMEM);
+ }
+
+ ret = mga_warp_install_microcode( dev_priv );
+ if ( ret < 0 ) {
+ DRM_ERROR( "failed to install WARP ucode!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(ret);
+ }
+
+ ret = mga_warp_init( dev_priv );
+ if ( ret < 0 ) {
+ DRM_ERROR( "failed to init WARP engine!\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(ret);
+ }
+
+ dev_priv->prim.status = (u32 *)dev_priv->status->handle;
+
+ mga_do_wait_for_idle( dev_priv );
+
+ /* Init the primary DMA registers.
+ */
+ MGA_WRITE( MGA_PRIMADDRESS,
+ dev_priv->primary->offset | MGA_DMA_GENERAL );
+#if 0
+ MGA_WRITE( MGA_PRIMPTR,
+ virt_to_bus((void *)dev_priv->prim.status) |
+ MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */
+ MGA_PRIMPTREN1 ); /* DWGSYNC */
+#endif
+
+ dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
+ dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
+ + dev_priv->primary->size);
+ dev_priv->prim.size = dev_priv->primary->size;
+
+ dev_priv->prim.tail = 0;
+ dev_priv->prim.space = dev_priv->prim.size;
+ dev_priv->prim.wrapped = 0;
+
+ dev_priv->prim.last_flush = 0;
+ dev_priv->prim.last_wrap = 0;
+
+ dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
+
+#ifdef __linux__
+ spin_lock_init( &dev_priv->prim.list_lock );
+#endif /* __linux__ */
+
+ dev_priv->prim.status[0] = dev_priv->primary->offset;
+ dev_priv->prim.status[1] = 0;
+
+ dev_priv->sarea_priv->last_wrap = 0;
+ dev_priv->sarea_priv->last_frame.head = 0;
+ dev_priv->sarea_priv->last_frame.wrap = 0;
+
+ if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
+ DRM_ERROR( "could not initialize freelist\n" );
+ /* Assign dev_private so we can do cleanup. */
+ dev->dev_private = (void *)dev_priv;
+ mga_do_cleanup_dma( dev );
+ DRM_OS_RETURN(ENOMEM);
+ }
+
+ /* Make dev_private visable to others. */
+ dev->dev_private = (void *)dev_priv;
+ return 0;
+}
+
+int mga_do_cleanup_dma( drm_device_t *dev )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( dev->dev_private ) {
+ drm_mga_private_t *dev_priv = dev->dev_private;
+
+ DRM_IOREMAPFREE( dev_priv->warp );
+ DRM_IOREMAPFREE( dev_priv->primary );
+ DRM_IOREMAPFREE( dev_priv->buffers );
+
+ if ( dev_priv->head != NULL ) {
+ mga_freelist_cleanup( dev );
+ }
+
+ DRM(free)( dev->dev_private, sizeof(drm_mga_private_t),
+ DRM_MEM_DRIVER );
+ dev->dev_private = NULL;
+ }
+
+ return 0;
+}
+
+int mga_dma_init( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_mga_init_t init;
+
+ DRM_OS_KRNFROMUSR( init, (drm_mga_init_t *) data, sizeof(init) );
+
+ switch ( init.func ) {
+ case MGA_INIT_DMA:
+ return mga_do_init_dma( dev, &init );
+ case MGA_CLEANUP_DMA:
+ return mga_do_cleanup_dma( dev );
+ }
+
+ DRM_OS_RETURN( EINVAL );
+}
+
+
+/* ================================================================
+ * Primary DMA stream management
+ */
+
+int mga_dma_flush( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_lock_t lock;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( lock, (drm_lock_t *) data, sizeof(lock) );
+
+ DRM_DEBUG( "%s: %s%s%s\n",
+ __FUNCTION__,
+ (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
+ (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
+ (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" );
+
+ WRAP_WAIT_WITH_RETURN( dev_priv );
+
+ if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {
+ mga_do_dma_flush( dev_priv );
+ }
+
+ if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
+#if MGA_DMA_DEBUG
+ int ret = mga_do_wait_for_idle( dev_priv );
+#ifdef __linux__
+ if ( ret < 0 )
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if ( ret )
+#endif /* __FreeBSD__ */
+ DRM_INFO( __FUNCTION__": -EBUSY\n" );
+ return ret;
+#else
+ return mga_do_wait_for_idle( dev_priv );
+#endif
+ } else {
+ return 0;
+ }
+}
+
+int mga_dma_reset( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ return mga_do_dma_reset( dev_priv );
+}
+
+
+/* ================================================================
+ * DMA buffer management
+ */
+
+#if 0
+static int mga_dma_get_buffers( drm_device_t *dev, drm_dma_t *d )
+{
+ drm_buf_t *buf;
+ int i;
+
+ for ( i = d->granted_count ; i < d->request_count ; i++ ) {
+ buf = mga_freelist_get( dev );
+ if ( !buf )
+ DRM_OS_RETURN( EAGAIN );
+
+ buf->pid = current->pid;
+
+ if ( DRM_OS_COPYTOUSR( &d->request_indices[i],
+ &buf->idx, sizeof(buf->idx) ) )
+ DRM_OS_RETURN( EFAULT );
+ if ( DRM_OS_COPYTOUSR( &d->request_sizes[i],
+ &buf->total, sizeof(buf->total) ) )
+ DRM_OS_RETURN( EFAULT );
+
+ d->granted_count++;
+ }
+ return 0;
+}
+#endif /* 0 */
+
+int mga_dma_buffers( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+ drm_dma_t d;
+ drm_buf_t *buf;
+ int i;
+ int ret = 0;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( d, (drm_dma_t *) data, 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_OS_CURRENTPID, d.send_count );
+ DRM_OS_RETURN( 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_OS_CURRENTPID, d.request_count, dma->buf_count );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ WRAP_TEST_WITH_RETURN( dev_priv );
+
+ d.granted_count = 0;
+
+ if ( d.request_count ) {
+ for ( i = d.granted_count ; i < d.request_count ; i++ ) {
+ buf = mga_freelist_get( dev );
+ if ( !buf )
+ DRM_OS_RETURN( EAGAIN );
+
+ buf->pid = DRM_OS_CURRENTPID;
+
+ if ( DRM_OS_COPYTOUSR( &d.request_indices[i],
+ &buf->idx, sizeof(buf->idx) ) )
+ DRM_OS_RETURN( EFAULT );
+ if ( DRM_OS_COPYTOUSR( &d.request_sizes[i],
+ &buf->total, sizeof(buf->total) ) )
+ DRM_OS_RETURN( EFAULT );
+
+ d.granted_count++;
+ }
+ ret = 0;
+ }
+
+ DRM_OS_KRNTOUSR( (drm_dma_t *) data, d, sizeof(d) );
+
+ return ret;
+}
diff --git a/sys/dev/drm/mga_drm.h b/sys/dev/drm/mga_drm.h
new file mode 100644
index 0000000..25bb66a
--- /dev/null
+++ b/sys/dev/drm/mga_drm.h
@@ -0,0 +1,312 @@
+/* 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 <keithw@valinux.com>
+ *
+ * Rewritten by:
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * $FreeBSD$
+ */
+
+#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_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
+
+#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;
+
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmMga.h)
+ */
+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_fullscreen {
+ enum {
+ MGA_INIT_FULLSCREEN = 0x01,
+ MGA_CLEANUP_FULLSCREEN = 0x02
+ } func;
+} drm_mga_fullscreen_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;
+
+#endif
diff --git a/sys/dev/drm/mga_drv.c b/sys/dev/drm/mga_drv.c
new file mode 100644
index 0000000..62728a2
--- /dev/null
+++ b/sys/dev/drm/mga_drv.c
@@ -0,0 +1,137 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __linux__
+#include <linux/config.h>
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <pci/pcivar.h>
+#include <opt_drm_linux.h>
+#endif /* __FreeBSD__ */
+
+#include "dev/drm/mga.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/mga_drv.h"
+
+#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME "mga"
+#define DRIVER_DESC "Matrox G200/G400"
+#define DRIVER_DATE "20010321"
+
+#define DRIVER_MAJOR 3
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 2
+
+#ifdef __FreeBSD__
+/* List acquired from xc/xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h
+ * Please report to eanholt@gladstone.uoregon.edu if your chip isn't
+ * represented in the list or if the information is incorrect.
+ */
+/* PCI cards are not supported with DRI under FreeBSD.
+ */
+drm_chipinfo_t DRM(devicelist)[] = {
+ {0x102b, 0x0520, 0, "Matrox G200 (PCI)"},
+ {0x102b, 0x0521, 1, "Matrox G200 (AGP)"},
+ {0x102b, 0x0525, 1, "Matrox G400/G450 (AGP)"},
+ {0x102b, 0x2527, 1, "Matrox G550 (AGP)"},
+ {0, 0, 0, NULL}
+};
+#endif /* __FreeBSD__ */
+
+#define DRIVER_IOCTLS \
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mga_dma_buffers, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)] = { mga_dma_init, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)] = { mga_dma_flush, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_RESET)] = { mga_dma_reset, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)] = { mga_dma_swap, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)] = { mga_dma_clear, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)] = { mga_dma_blit, 1, 0 },
+
+
+#define __HAVE_COUNTERS 3
+#define __HAVE_COUNTER6 _DRM_STAT_IRQ
+#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY
+
+
+#include "dev/drm/drm_agpsupport.h"
+#include "dev/drm/drm_auth.h"
+#include "dev/drm/drm_bufs.h"
+#include "dev/drm/drm_context.h"
+#include "dev/drm/drm_dma.h"
+#include "dev/drm/drm_drawable.h"
+#include "dev/drm/drm_drv.h"
+
+#ifdef __linux__
+#ifndef MODULE
+/* DRM(options) is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO). It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+
+/* JH- We have to hand expand the string ourselves because of the cpp. If
+ * anyone can think of a way that we can fit into the __setup macro without
+ * changing it, then please send the solution my way.
+ */
+static int __init mga_options( char *str )
+{
+ DRM(parse_options)( str );
+ return 1;
+}
+
+__setup( DRIVER_NAME "=", mga_options );
+#endif
+#endif /* __linux__ */
+
+#include "dev/drm/drm_fops.h"
+#include "dev/drm/drm_init.h"
+#include "dev/drm/drm_ioctl.h"
+#include "dev/drm/drm_lock.h"
+#include "dev/drm/drm_memory.h"
+#include "dev/drm/drm_vm.h"
+#ifdef __linux__
+#include "dev/drm/drm_proc.h"
+#include "dev/drm/drm_stub.h"
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include "dev/drm/drm_sysctl.h"
+
+DRIVER_MODULE(mga, pci, mga_driver, mga_devclass, 0, 0);
+#endif /* __FreeBSD__ */
diff --git a/sys/dev/drm/mga_drv.h b/sys/dev/drm/mga_drv.h
new file mode 100644
index 0000000..002b3c7
--- /dev/null
+++ b/sys/dev/drm/mga_drv.h
@@ -0,0 +1,640 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __MGA_DRV_H__
+#define __MGA_DRV_H__
+
+#ifndef u8
+#define u8 u_int8_t
+#define u16 u_int16_t
+#define u32 u_int32_t
+#endif
+
+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;
+
+ spinlock_t list_lock;
+} 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;
+
+ u32 clear_cmd;
+ u32 maccess;
+
+ 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_map_t *sarea;
+ drm_map_t *fb;
+ drm_map_t *mmio;
+ drm_map_t *status;
+ drm_map_t *warp;
+ drm_map_t *primary;
+ drm_map_t *buffers;
+ drm_map_t *agp_textures;
+} drm_mga_private_t;
+
+ /* mga_dma.c */
+extern int mga_dma_init( DRM_OS_IOCTL );
+extern int mga_dma_flush( DRM_OS_IOCTL );
+extern int mga_dma_reset( DRM_OS_IOCTL );
+extern int mga_dma_buffers( DRM_OS_IOCTL );
+
+extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv );
+extern int mga_do_dma_idle( drm_mga_private_t *dev_priv );
+extern int mga_do_dma_reset( drm_mga_private_t *dev_priv );
+extern int mga_do_engine_reset( drm_mga_private_t *dev_priv );
+extern int mga_do_cleanup_dma( drm_device_t *dev );
+
+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_state.c */
+extern int mga_dma_clear( DRM_OS_IOCTL );
+extern int mga_dma_swap( DRM_OS_IOCTL );
+extern int mga_dma_vertex( DRM_OS_IOCTL );
+extern int mga_dma_indices( DRM_OS_IOCTL );
+extern int mga_dma_iload( DRM_OS_IOCTL );
+extern int mga_dma_blit( DRM_OS_IOCTL );
+
+ /* mga_warp.c */
+extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
+extern int mga_warp_init( drm_mga_private_t *dev_priv );
+
+#define mga_flush_write_combine() DRM_OS_READMEMORYBARRIER
+
+#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 )
+
+#ifdef __alpha__
+#define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg)))
+#define MGA_WRITE( reg, val ) do { wmb(); MGA_DEREF( reg ) = val; } while (0)
+#define MGA_WRITE8( reg, val ) do { wmb(); MGA_DEREF8( reg ) = val; } while (0)
+
+static inline u32 _MGA_READ(u32 *addr)
+{
+ mb();
+ return *(volatile u32 *)addr;
+}
+
+#else
+#define MGA_READ( reg ) MGA_DEREF( reg )
+#define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0)
+#define MGA_WRITE8( reg, val ) do { MGA_DEREF8( reg ) = val; } while (0)
+#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 LOCK_TEST_WITH_RETURN( dev ) \
+do { \
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
+ dev->lock.pid != DRM_OS_CURRENTPID ) { \
+ DRM_ERROR( "%s called without lock held\n", \
+ __FUNCTION__ ); \
+ DRM_OS_RETURN( EINVAL ); \
+ } \
+} 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( __FUNCTION__": wrap...\n" ); \
+ DRM_OS_RETURN( 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 ) ) { \
+ if ( MGA_DMA_DEBUG ) \
+ DRM_INFO( __FUNCTION__": wrap...\n" ); \
+ DRM_OS_RETURN( 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%x\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( __FUNCTION__ ":\n" ); \
+ 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%04x\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_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_IEN 0x1e1c
+# define MGA_SOFTRAPIEN (1 << 0)
+
+#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_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
+
+/* 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
diff --git a/sys/dev/drm/mga_state.c b/sys/dev/drm/mga_state.c
new file mode 100644
index 0000000..8628b0d
--- /dev/null
+++ b/sys/dev/drm/mga_state.c
@@ -0,0 +1,1068 @@
+/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*-
+ * Created: Thu Jan 27 02:53:43 2000 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 <keithw@valinux.com>
+ *
+ * Rewritten by:
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/mga.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/mga_drv.h"
+#include "dev/drm/drm.h"
+
+
+/* ================================================================
+ * DMA hardware state programming functions
+ */
+
+static void mga_emit_clip_rect( drm_mga_private_t *dev_priv,
+ drm_clip_rect_t *box )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ unsigned int pitch = dev_priv->front_pitch;
+ DMA_LOCALS;
+
+ BEGIN_DMA( 2 );
+
+ /* Force reset of DWGCTL on G400 (eliminates clip disable bit).
+ */
+ if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
+ DMA_BLOCK( MGA_DWGCTL, ctx->dwgctl,
+ MGA_LEN + MGA_EXEC, 0x80000000,
+ MGA_DWGCTL, ctx->dwgctl,
+ MGA_LEN + MGA_EXEC, 0x80000000 );
+ }
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_CXBNDRY, (box->x2 << 16) | box->x1,
+ MGA_YTOP, box->y1 * pitch,
+ MGA_YBOT, box->y2 * pitch );
+
+ ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_context( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ DMA_LOCALS;
+
+ BEGIN_DMA( 3 );
+
+ DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
+ MGA_MACCESS, ctx->maccess,
+ MGA_PLNWT, ctx->plnwt,
+ MGA_DWGCTL, ctx->dwgctl );
+
+ DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
+ MGA_FOGCOL, ctx->fogcolor,
+ MGA_WFLAG, ctx->wflag,
+ MGA_ZORG, dev_priv->depth_offset );
+
+ DMA_BLOCK( MGA_FCOL, ctx->fcol,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000 );
+
+ ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_context( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ DMA_LOCALS;
+
+ BEGIN_DMA( 4 );
+
+ DMA_BLOCK( MGA_DSTORG, ctx->dstorg,
+ MGA_MACCESS, ctx->maccess,
+ MGA_PLNWT, ctx->plnwt,
+ MGA_DWGCTL, ctx->dwgctl );
+
+ DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl,
+ MGA_FOGCOL, ctx->fogcolor,
+ MGA_WFLAG, ctx->wflag,
+ MGA_ZORG, dev_priv->depth_offset );
+
+ DMA_BLOCK( MGA_WFLAG1, ctx->wflag,
+ MGA_TDUALSTAGE0, ctx->tdualstage0,
+ MGA_TDUALSTAGE1, ctx->tdualstage1,
+ MGA_FCOL, ctx->fcol );
+
+ DMA_BLOCK( MGA_STENCIL, ctx->stencil,
+ MGA_STENCILCTL, ctx->stencilctl,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000 );
+
+ ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_tex0( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+ DMA_LOCALS;
+
+ BEGIN_DMA( 4 );
+
+ DMA_BLOCK( MGA_TEXCTL2, tex->texctl2,
+ MGA_TEXCTL, tex->texctl,
+ MGA_TEXFILTER, tex->texfilter,
+ MGA_TEXBORDERCOL, tex->texbordercol );
+
+ DMA_BLOCK( MGA_TEXORG, tex->texorg,
+ MGA_TEXORG1, tex->texorg1,
+ MGA_TEXORG2, tex->texorg2,
+ MGA_TEXORG3, tex->texorg3 );
+
+ DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
+ MGA_TEXWIDTH, tex->texwidth,
+ MGA_TEXHEIGHT, tex->texheight,
+ MGA_WR24, tex->texwidth );
+
+ DMA_BLOCK( MGA_WR34, tex->texheight,
+ MGA_TEXTRANS, 0x0000ffff,
+ MGA_TEXTRANSHIGH, 0x0000ffff,
+ MGA_DMAPAD, 0x00000000 );
+
+ ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+ DMA_LOCALS;
+
+ BEGIN_DMA( 6 );
+
+ DMA_BLOCK( MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
+ MGA_TEXCTL, tex->texctl,
+ MGA_TEXFILTER, tex->texfilter,
+ MGA_TEXBORDERCOL, tex->texbordercol );
+
+ DMA_BLOCK( MGA_TEXORG, tex->texorg,
+ MGA_TEXORG1, tex->texorg1,
+ MGA_TEXORG2, tex->texorg2,
+ MGA_TEXORG3, tex->texorg3 );
+
+ DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
+ MGA_TEXWIDTH, tex->texwidth,
+ MGA_TEXHEIGHT, tex->texheight,
+ MGA_WR49, 0x00000000 );
+
+ DMA_BLOCK( MGA_WR57, 0x00000000,
+ MGA_WR53, 0x00000000,
+ MGA_WR61, 0x00000000,
+ MGA_WR52, MGA_G400_WR_MAGIC );
+
+ DMA_BLOCK( MGA_WR60, MGA_G400_WR_MAGIC,
+ MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
+ MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
+ MGA_DMAPAD, 0x00000000 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_TEXTRANS, 0x0000ffff,
+ MGA_TEXTRANSHIGH, 0x0000ffff );
+
+ ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
+ DMA_LOCALS;
+
+ BEGIN_DMA( 5 );
+
+ DMA_BLOCK( MGA_TEXCTL2, (tex->texctl2 |
+ MGA_MAP1_ENABLE |
+ MGA_G400_TC2_MAGIC),
+ MGA_TEXCTL, tex->texctl,
+ MGA_TEXFILTER, tex->texfilter,
+ MGA_TEXBORDERCOL, tex->texbordercol );
+
+ DMA_BLOCK( MGA_TEXORG, tex->texorg,
+ MGA_TEXORG1, tex->texorg1,
+ MGA_TEXORG2, tex->texorg2,
+ MGA_TEXORG3, tex->texorg3 );
+
+ DMA_BLOCK( MGA_TEXORG4, tex->texorg4,
+ MGA_TEXWIDTH, tex->texwidth,
+ MGA_TEXHEIGHT, tex->texheight,
+ MGA_WR49, 0x00000000 );
+
+ DMA_BLOCK( MGA_WR57, 0x00000000,
+ MGA_WR53, 0x00000000,
+ MGA_WR61, 0x00000000,
+ MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC );
+
+ DMA_BLOCK( MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
+ MGA_TEXTRANS, 0x0000ffff,
+ MGA_TEXTRANSHIGH, 0x0000ffff,
+ MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC );
+
+ ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int pipe = sarea_priv->warp_pipe;
+ DMA_LOCALS;
+
+ BEGIN_DMA( 3 );
+
+ DMA_BLOCK( MGA_WIADDR, MGA_WMODE_SUSPEND,
+ MGA_WVRTXSZ, 0x00000007,
+ MGA_WFLAG, 0x00000000,
+ MGA_WR24, 0x00000000 );
+
+ DMA_BLOCK( MGA_WR25, 0x00000100,
+ MGA_WR34, 0x00000000,
+ MGA_WR42, 0x0000ffff,
+ MGA_WR60, 0x0000ffff );
+
+ /* Padding required to to hardware bug.
+ */
+ DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
+ MGA_WMODE_START |
+ MGA_WAGP_ENABLE) );
+
+ ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int pipe = sarea_priv->warp_pipe;
+ DMA_LOCALS;
+
+ BEGIN_DMA( 10 );
+
+ DMA_BLOCK( MGA_WIADDR2, MGA_WMODE_SUSPEND,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000 );
+
+ if ( pipe & MGA_T2 ) {
+ DMA_BLOCK( MGA_WVRTXSZ, 0x00001e09,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000 );
+
+ DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x1e000000 );
+ } else {
+ if ( dev_priv->warp_pipe & MGA_T2 ) {
+ /* Flush the WARP pipe */
+ DMA_BLOCK( MGA_YDST, 0x00000000,
+ MGA_FXLEFT, 0x00000000,
+ MGA_FXRIGHT, 0x00000001,
+ MGA_DWGCTL, MGA_DWGCTL_FLUSH );
+
+ DMA_BLOCK( MGA_LEN + MGA_EXEC, 0x00000001,
+ MGA_DWGSYNC, 0x00007000,
+ MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+ MGA_LEN + MGA_EXEC, 0x00000000 );
+
+ DMA_BLOCK( MGA_TEXCTL2, (MGA_DUALTEX |
+ MGA_G400_TC2_MAGIC),
+ MGA_LEN + MGA_EXEC, 0x00000000,
+ MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+ MGA_DMAPAD, 0x00000000 );
+ }
+
+ DMA_BLOCK( MGA_WVRTXSZ, 0x00001807,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000 );
+
+ DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x00000000,
+ MGA_WACCEPTSEQ, 0x18000000 );
+ }
+
+ DMA_BLOCK( MGA_WFLAG, 0x00000000,
+ MGA_WFLAG1, 0x00000000,
+ MGA_WR56, MGA_G400_WR56_MAGIC,
+ MGA_DMAPAD, 0x00000000 );
+
+ DMA_BLOCK( MGA_WR49, 0x00000000, /* tex0 */
+ MGA_WR57, 0x00000000, /* tex0 */
+ MGA_WR53, 0x00000000, /* tex1 */
+ MGA_WR61, 0x00000000 ); /* tex1 */
+
+ DMA_BLOCK( MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */
+ MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */
+ MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */
+ MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */
+
+ /* Padding required to to hardware bug */
+ DMA_BLOCK( MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_DMAPAD, 0xffffffff,
+ MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
+ MGA_WMODE_START |
+ MGA_WAGP_ENABLE) );
+
+ ADVANCE_DMA();
+}
+
+static void mga_g200_emit_state( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+ if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
+ mga_g200_emit_pipe( dev_priv );
+ dev_priv->warp_pipe = sarea_priv->warp_pipe;
+ }
+
+ if ( dirty & MGA_UPLOAD_CONTEXT ) {
+ mga_g200_emit_context( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+ }
+
+ if ( dirty & MGA_UPLOAD_TEX0 ) {
+ mga_g200_emit_tex0( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+ }
+}
+
+static void mga_g400_emit_state( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+ int multitex = sarea_priv->warp_pipe & MGA_T2;
+
+ if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
+ mga_g400_emit_pipe( dev_priv );
+ dev_priv->warp_pipe = sarea_priv->warp_pipe;
+ }
+
+ if ( dirty & MGA_UPLOAD_CONTEXT ) {
+ mga_g400_emit_context( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+ }
+
+ if ( dirty & MGA_UPLOAD_TEX0 ) {
+ mga_g400_emit_tex0( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+ }
+
+ if ( (dirty & MGA_UPLOAD_TEX1) && multitex ) {
+ mga_g400_emit_tex1( dev_priv );
+ sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
+ }
+}
+
+
+/* ================================================================
+ * SAREA state verification
+ */
+
+/* Disallow all write destinations except the front and backbuffer.
+ */
+static int mga_verify_context( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+
+ if ( ctx->dstorg != dev_priv->front_offset &&
+ ctx->dstorg != dev_priv->back_offset ) {
+ DRM_ERROR( "*** bad DSTORG: %x (front %x, back %x)\n\n",
+ ctx->dstorg, dev_priv->front_offset,
+ dev_priv->back_offset );
+ ctx->dstorg = 0;
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ return 0;
+}
+
+/* Disallow texture reads from PCI space.
+ */
+static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
+ unsigned int org;
+
+ org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
+
+ if ( org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI) ) {
+ DRM_ERROR( "*** bad TEXORG: 0x%x, unit %d\n",
+ tex->texorg, unit );
+ tex->texorg = 0;
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ return 0;
+}
+
+static int mga_verify_state( drm_mga_private_t *dev_priv )
+{
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+ int ret = 0;
+
+ if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+ if ( dirty & MGA_UPLOAD_CONTEXT )
+ ret |= mga_verify_context( dev_priv );
+
+ if ( dirty & MGA_UPLOAD_TEX0 )
+ ret |= mga_verify_tex( dev_priv, 0 );
+
+ if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
+ if ( dirty & MGA_UPLOAD_TEX1 )
+ ret |= mga_verify_tex( dev_priv, 1 );
+
+ if ( dirty & MGA_UPLOAD_PIPE )
+ ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES );
+ } else {
+ if ( dirty & MGA_UPLOAD_PIPE )
+ ret |= ( sarea_priv->warp_pipe > MGA_MAX_G200_PIPES );
+ }
+
+ return ( ret == 0 );
+}
+
+static int mga_verify_iload( drm_mga_private_t *dev_priv,
+ unsigned int dstorg, unsigned int length )
+{
+ if ( dstorg < dev_priv->texture_offset ||
+ dstorg + length > (dev_priv->texture_offset +
+ dev_priv->texture_size) ) {
+ DRM_ERROR( "*** bad iload DSTORG: 0x%x\n", dstorg );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ if ( length & MGA_ILOAD_MASK ) {
+ DRM_ERROR( "*** bad iload length: 0x%x\n",
+ length & MGA_ILOAD_MASK );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ return 0;
+}
+
+static int mga_verify_blit( drm_mga_private_t *dev_priv,
+ unsigned int srcorg, unsigned int dstorg )
+{
+ if ( (srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
+ (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) {
+ DRM_ERROR( "*** bad blit: src=0x%x dst=0x%x\n",
+ srcorg, dstorg );
+ DRM_OS_RETURN( EINVAL );
+ }
+ return 0;
+}
+
+
+/* ================================================================
+ *
+ */
+
+static void mga_dma_dispatch_clear( drm_device_t *dev,
+ drm_mga_clear_t *clear )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int nbox = sarea_priv->nbox;
+ int i;
+ DMA_LOCALS;
+ DRM_DEBUG( __FUNCTION__ ":\n" );
+
+ BEGIN_DMA( 1 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGSYNC, 0x00007100,
+ MGA_DWGSYNC, 0x00007000 );
+
+ ADVANCE_DMA();
+
+ for ( i = 0 ; i < nbox ; i++ ) {
+ drm_clip_rect_t *box = &pbox[i];
+ u32 height = box->y2 - box->y1;
+
+ DRM_DEBUG( " from=%d,%d to=%d,%d\n",
+ box->x1, box->y1, box->x2, box->y2 );
+
+ if ( clear->flags & MGA_FRONT ) {
+ BEGIN_DMA( 2 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, clear->color_mask,
+ MGA_YDSTLEN, (box->y1 << 16) | height,
+ MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_FCOL, clear->clear_color,
+ MGA_DSTORG, dev_priv->front_offset,
+ MGA_DWGCTL + MGA_EXEC,
+ dev_priv->clear_cmd );
+
+ ADVANCE_DMA();
+ }
+
+
+ if ( clear->flags & MGA_BACK ) {
+ BEGIN_DMA( 2 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, clear->color_mask,
+ MGA_YDSTLEN, (box->y1 << 16) | height,
+ MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_FCOL, clear->clear_color,
+ MGA_DSTORG, dev_priv->back_offset,
+ MGA_DWGCTL + MGA_EXEC,
+ dev_priv->clear_cmd );
+
+ ADVANCE_DMA();
+ }
+
+ if ( clear->flags & MGA_DEPTH ) {
+ BEGIN_DMA( 2 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, clear->depth_mask,
+ MGA_YDSTLEN, (box->y1 << 16) | height,
+ MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_FCOL, clear->clear_depth,
+ MGA_DSTORG, dev_priv->depth_offset,
+ MGA_DWGCTL + MGA_EXEC,
+ dev_priv->clear_cmd );
+
+ ADVANCE_DMA();
+ }
+
+ }
+
+ BEGIN_DMA( 1 );
+
+ /* Force reset of DWGCTL */
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, ctx->plnwt,
+ MGA_DWGCTL, ctx->dwgctl );
+
+ ADVANCE_DMA();
+
+ FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_swap( drm_device_t *dev )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int nbox = sarea_priv->nbox;
+ int i;
+ DMA_LOCALS;
+ DRM_DEBUG( __FUNCTION__ ":\n" );
+
+ sarea_priv->last_frame.head = dev_priv->prim.tail;
+ sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
+
+ BEGIN_DMA( 4 + nbox );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGSYNC, 0x00007100,
+ MGA_DWGSYNC, 0x00007000 );
+
+ DMA_BLOCK( MGA_DSTORG, dev_priv->front_offset,
+ MGA_MACCESS, dev_priv->maccess,
+ MGA_SRCORG, dev_priv->back_offset,
+ MGA_AR5, dev_priv->front_pitch );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, 0xffffffff,
+ MGA_DWGCTL, MGA_DWGCTL_COPY );
+
+ for ( i = 0 ; i < nbox ; i++ ) {
+ drm_clip_rect_t *box = &pbox[i];
+ u32 height = box->y2 - box->y1;
+ u32 start = box->y1 * dev_priv->front_pitch;
+
+ DRM_DEBUG( " from=%d,%d to=%d,%d\n",
+ box->x1, box->y1, box->x2, box->y2 );
+
+ DMA_BLOCK( MGA_AR0, start + box->x2 - 1,
+ MGA_AR3, start + box->x1,
+ MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+ MGA_YDSTLEN + MGA_EXEC,
+ (box->y1 << 16) | height );
+ }
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, ctx->plnwt,
+ MGA_SRCORG, dev_priv->front_offset,
+ MGA_DWGCTL, ctx->dwgctl );
+
+ ADVANCE_DMA();
+
+ FLUSH_DMA();
+
+ DRM_DEBUG( "%s... done.\n", __FUNCTION__ );
+}
+
+static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ u32 address = (u32) buf->bus_address;
+ u32 length = (u32) buf->used;
+ int i = 0;
+ DMA_LOCALS;
+ DRM_DEBUG( "vertex: buf=%d used=%d\n", buf->idx, buf->used );
+
+ if ( buf->used ) {
+ buf_priv->dispatched = 1;
+
+ MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
+
+ do {
+ if ( i < sarea_priv->nbox ) {
+ mga_emit_clip_rect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+
+ BEGIN_DMA( 1 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_SECADDRESS, (address |
+ MGA_DMA_VERTEX),
+ MGA_SECEND, ((address + length) |
+ MGA_PAGPXFER) );
+
+ ADVANCE_DMA();
+ } while ( ++i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ AGE_BUFFER( buf_priv );
+ buf->pending = 0;
+ buf->used = 0;
+ buf_priv->dispatched = 0;
+
+ mga_freelist_put( dev, buf );
+ }
+
+ FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
+ unsigned int start, unsigned int end )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ u32 address = (u32) buf->bus_address;
+ int i = 0;
+ DMA_LOCALS;
+ DRM_DEBUG( "indices: buf=%d start=%d end=%d\n", buf->idx, start, end );
+
+ if ( start != end ) {
+ buf_priv->dispatched = 1;
+
+ MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
+
+ do {
+ if ( i < sarea_priv->nbox ) {
+ mga_emit_clip_rect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+
+ BEGIN_DMA( 1 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_SETUPADDRESS, address + start,
+ MGA_SETUPEND, ((address + end) |
+ MGA_PAGPXFER) );
+
+ ADVANCE_DMA();
+ } while ( ++i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ AGE_BUFFER( buf_priv );
+ buf->pending = 0;
+ buf->used = 0;
+ buf_priv->dispatched = 0;
+
+ mga_freelist_put( dev, buf );
+ }
+
+ FLUSH_DMA();
+}
+
+/* This copies a 64 byte aligned agp region to the frambuffer with a
+ * standard blit, the ioctl needs to do checking.
+ */
+static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,
+ unsigned int dstorg, unsigned int length )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+ drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
+ u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM;
+ u32 y2;
+ DMA_LOCALS;
+ DRM_DEBUG( "%s: buf=%d used=%d\n",
+ __FUNCTION__, buf->idx, buf->used );
+
+ y2 = length / 64;
+
+ BEGIN_DMA( 5 );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGSYNC, 0x00007100,
+ MGA_DWGSYNC, 0x00007000 );
+
+ DMA_BLOCK( MGA_DSTORG, dstorg,
+ MGA_MACCESS, 0x00000000,
+ MGA_SRCORG, srcorg,
+ MGA_AR5, 64 );
+
+ DMA_BLOCK( MGA_PITCH, 64,
+ MGA_PLNWT, 0xffffffff,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGCTL, MGA_DWGCTL_COPY );
+
+ DMA_BLOCK( MGA_AR0, 63,
+ MGA_AR3, 0,
+ MGA_FXBNDRY, (63 << 16) | 0,
+ MGA_YDSTLEN + MGA_EXEC, y2 );
+
+ DMA_BLOCK( MGA_PLNWT, ctx->plnwt,
+ MGA_SRCORG, dev_priv->front_offset,
+ MGA_PITCH, dev_priv->front_pitch,
+ MGA_DWGSYNC, 0x00007000 );
+
+ ADVANCE_DMA();
+
+ AGE_BUFFER( buf_priv );
+
+ buf->pending = 0;
+ buf->used = 0;
+ buf_priv->dispatched = 0;
+
+ mga_freelist_put( dev, buf );
+
+ FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_blit( drm_device_t *dev,
+ drm_mga_blit_t *blit )
+{
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int nbox = sarea_priv->nbox;
+ u32 scandir = 0, i;
+ DMA_LOCALS;
+ DRM_DEBUG( __FUNCTION__ ":\n" );
+
+ BEGIN_DMA( 4 + nbox );
+
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_DMAPAD, 0x00000000,
+ MGA_DWGSYNC, 0x00007100,
+ MGA_DWGSYNC, 0x00007000 );
+
+ DMA_BLOCK( MGA_DWGCTL, MGA_DWGCTL_COPY,
+ MGA_PLNWT, blit->planemask,
+ MGA_SRCORG, blit->srcorg,
+ MGA_DSTORG, blit->dstorg );
+
+ DMA_BLOCK( MGA_SGN, scandir,
+ MGA_MACCESS, dev_priv->maccess,
+ MGA_AR5, blit->ydir * blit->src_pitch,
+ MGA_PITCH, blit->dst_pitch );
+
+ for ( i = 0 ; i < nbox ; i++ ) {
+ int srcx = pbox[i].x1 + blit->delta_sx;
+ int srcy = pbox[i].y1 + blit->delta_sy;
+ int dstx = pbox[i].x1 + blit->delta_dx;
+ int dsty = pbox[i].y1 + blit->delta_dy;
+ int h = pbox[i].y2 - pbox[i].y1;
+ int w = pbox[i].x2 - pbox[i].x1 - 1;
+ int start;
+
+ if ( blit->ydir == -1 ) {
+ srcy = blit->height - srcy - 1;
+ }
+
+ start = srcy * blit->src_pitch + srcx;
+
+ DMA_BLOCK( MGA_AR0, start + w,
+ MGA_AR3, start,
+ MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
+ MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h );
+ }
+
+ /* Do something to flush AGP?
+ */
+
+ /* Force reset of DWGCTL */
+ DMA_BLOCK( MGA_DMAPAD, 0x00000000,
+ MGA_PLNWT, ctx->plnwt,
+ MGA_PITCH, dev_priv->front_pitch,
+ MGA_DWGCTL, ctx->dwgctl );
+
+ ADVANCE_DMA();
+}
+
+
+/* ================================================================
+ *
+ */
+
+int mga_dma_clear( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_clear_t clear;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( clear, (drm_mga_clear_t *) data, sizeof(clear) );
+
+ if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+ WRAP_TEST_WITH_RETURN( dev_priv );
+
+ mga_dma_dispatch_clear( dev, &clear );
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+ return 0;
+}
+
+int mga_dma_swap( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+ WRAP_TEST_WITH_RETURN( dev_priv );
+
+ mga_dma_dispatch_swap( dev );
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+ return 0;
+}
+
+int mga_dma_vertex( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_vertex_t vertex;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( vertex, (drm_mga_vertex_t *) data, sizeof(vertex) );
+
+ if(vertex.idx < 0 || vertex.idx > dma->buf_count) DRM_OS_RETURN( EINVAL );
+ buf = dma->buflist[vertex.idx];
+ buf_priv = buf->dev_private;
+
+ buf->used = vertex.used;
+ buf_priv->discard = vertex.discard;
+
+ if ( !mga_verify_state( dev_priv ) ) {
+ if ( vertex.discard ) {
+ if ( buf_priv->dispatched == 1 )
+ AGE_BUFFER( buf_priv );
+ buf_priv->dispatched = 0;
+ mga_freelist_put( dev, buf );
+ }
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ WRAP_TEST_WITH_RETURN( dev_priv );
+
+ mga_dma_dispatch_vertex( dev, buf );
+
+ return 0;
+}
+
+int mga_dma_indices( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_indices_t indices;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( indices, (drm_mga_indices_t *) data, sizeof(indices) );
+
+ if(indices.idx < 0 || indices.idx > dma->buf_count) DRM_OS_RETURN( EINVAL );
+
+ buf = dma->buflist[indices.idx];
+ buf_priv = buf->dev_private;
+
+ buf_priv->discard = indices.discard;
+
+ if ( !mga_verify_state( dev_priv ) ) {
+ if ( indices.discard ) {
+ if ( buf_priv->dispatched == 1 )
+ AGE_BUFFER( buf_priv );
+ buf_priv->dispatched = 0;
+ mga_freelist_put( dev, buf );
+ }
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ WRAP_TEST_WITH_RETURN( dev_priv );
+
+ mga_dma_dispatch_indices( dev, buf, indices.start, indices.end );
+
+ return 0;
+}
+
+int mga_dma_iload( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_buf_t *buf;
+ drm_mga_buf_priv_t *buf_priv;
+ drm_mga_iload_t iload;
+ DRM_DEBUG( __FUNCTION__ ":\n" );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( iload, (drm_mga_iload_t *) data, sizeof(iload) );
+
+#if 0
+ if ( mga_do_wait_for_idle( dev_priv ) ) {
+ if ( MGA_DMA_DEBUG )
+ DRM_INFO( __FUNCTION__": -EBUSY\n" );
+ DRM_OS_RETURN( EBUSY );
+ }
+#endif
+ if(iload.idx < 0 || iload.idx > dma->buf_count) DRM_OS_RETURN( EINVAL );
+
+ buf = dma->buflist[iload.idx];
+ buf_priv = buf->dev_private;
+
+ if ( mga_verify_iload( dev_priv, iload.dstorg, iload.length ) ) {
+ mga_freelist_put( dev, buf );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ WRAP_TEST_WITH_RETURN( dev_priv );
+
+ mga_dma_dispatch_iload( dev, buf, iload.dstorg, iload.length );
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+ return 0;
+}
+
+int mga_dma_blit( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_mga_blit_t blit;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( blit, (drm_mga_blit_t *) data, sizeof(blit) );
+
+ if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+ if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) )
+ DRM_OS_RETURN( EINVAL );
+
+ WRAP_TEST_WITH_RETURN( dev_priv );
+
+ mga_dma_dispatch_blit( dev, &blit );
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+ return 0;
+}
diff --git a/sys/dev/drm/mga_ucode.h b/sys/dev/drm/mga_ucode.h
new file mode 100644
index 0000000..3dd85e3
--- /dev/null
+++ b/sys/dev/drm/mga_ucode.h
@@ -0,0 +1,11647 @@
+/* mga_ucode.h -- Matrox G200/G400 WARP engine microcode -*- linux-c -*-
+ * Created: Thu Jan 11 21:20:43 2001 by gareth@valinux.com
+ *
+ * Copyright 1999 Matrox Graphics Inc.
+ * 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 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
+ * MATROX GRAPHICS INC., 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.
+ *
+ * Kernel-based WARP engine management:
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * WARP pipes are named according to the functions they perform, where:
+ *
+ * - T stands for computation of texture stage 0
+ * - T2 stands for computation of both texture stage 0 and texture stage 1
+ * - G stands for computation of triangle intensity (Gouraud interpolation)
+ * - Z stands for computation of Z buffer interpolation
+ * - S stands for computation of specular highlight
+ * - A stands for computation of the alpha channel
+ * - F stands for computation of vertex fog interpolation
+ */
+
+static unsigned char warp_g200_tgz[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x72, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x60, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x03, 0x80, 0x0A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x57, 0x39, 0x20, 0xE9,
+0x28, 0x19, 0x60, 0xEC,
+
+0x2B, 0x32, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0xB3, 0x05,
+0x00, 0xE0,
+0x16, 0x28, 0x20, 0xE9,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x2B, 0x20, 0xE9,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x85, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x84, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x82, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x7F, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgza[] = {
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x7D, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x6B, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x44, 0x4C, 0xB6,
+0x25, 0x44, 0x54, 0xB6,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x07, 0xC0, 0x44, 0xC6,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1F, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x3F, 0x3D, 0x5D, 0x9F,
+0x00, 0xE0,
+0x07, 0x20,
+
+0x00, 0x80, 0x00, 0xE8,
+0x28, 0x19, 0x60, 0xEC,
+
+0xB3, 0x05,
+0x00, 0xE0,
+0x00, 0x80, 0x00, 0xE8,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0x26, 0x1F, 0xDF,
+0x9D, 0x1F, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x9E, 0x3F, 0x4F, 0xE9,
+
+0x07, 0x07, 0x1F, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x9C, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x7A, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x79, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x77, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x74, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzaf[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x83, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x6F, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0D, 0x21, 0x1A, 0xB6,
+0x05, 0x21, 0x31, 0xB6,
+
+0x2D, 0x44, 0x4C, 0xB6,
+0x25, 0x44, 0x54, 0xB6,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x2F, 0xC0, 0x21, 0xC6,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x07, 0xC0, 0x44, 0xC6,
+
+0x17, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x2D, 0x20,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x1F, 0x62, 0x57, 0x9F,
+0x00, 0xE0,
+0x07, 0x20,
+
+0x3F, 0x3D, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x28, 0x19, 0x60, 0xEC,
+
+0xB3, 0x05,
+0x00, 0xE0,
+0x17, 0x26, 0x17, 0xDF,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x35, 0x17, 0x4F, 0xE9,
+
+0x1F, 0x26, 0x1F, 0xDF,
+0x9D, 0x1F, 0x4F, 0xE9,
+
+0x9E, 0x3F, 0x4F, 0xE9,
+0x39, 0x37, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x17, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x07, 0x07, 0x1F, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x31, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x9C, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x74, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x73, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x71, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6E, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzf[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x7F, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x6B, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0D, 0x21, 0x1A, 0xB6,
+0x05, 0x21, 0x31, 0xB6,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x2F, 0xC0, 0x21, 0xC6,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x17, 0x50, 0x56, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x00, 0x80, 0x00, 0xE8,
+0x28, 0x19, 0x60, 0xEC,
+
+0xB3, 0x05,
+0x00, 0xE0,
+0x00, 0x80, 0x00, 0xE8,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x17, 0x26, 0x17, 0xDF,
+0x35, 0x17, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x39, 0x37, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x17, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x31, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x78, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x77, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x75, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x72, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzs[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x8B, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x77, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x21, 0x1A, 0xB0,
+0x25, 0x21, 0x31, 0xB0,
+
+0x0D, 0x21, 0x1A, 0xB2,
+0x05, 0x21, 0x31, 0xB2,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x05, 0x20,
+0x0D, 0x20,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x2F, 0xC0, 0x21, 0xC0,
+
+0x16, 0x42, 0x56, 0x9F,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x21, 0x31, 0xB4,
+0x2D, 0x21, 0x1A, 0xB4,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0x05,
+0x00, 0xE0,
+0x28, 0x19, 0x60, 0xEC,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x26, 0x1E, 0xDF,
+
+0xA7, 0x1E, 0x4F, 0xE9,
+0x17, 0x26, 0x16, 0xDF,
+
+0x2D, 0x20,
+0x00, 0xE0,
+0xA8, 0x3F, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x1E, 0xAF,
+0x25, 0x20,
+0x00, 0xE0,
+
+0xA4, 0x16, 0x4F, 0xE9,
+0x0F, 0xC0, 0x21, 0xC2,
+
+0xA6, 0x80, 0x4F, 0xE9,
+0x1F, 0x62, 0x57, 0x9F,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0xE0,
+0x8F, 0x20,
+
+0xA5, 0x37, 0x4F, 0xE9,
+0x0F, 0x17, 0x0F, 0xAF,
+
+0x06, 0xC0, 0x21, 0xC4,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0xA3, 0x80, 0x4F, 0xE9,
+
+0x06, 0x20,
+0x00, 0xE0,
+0x1F, 0x26, 0x1F, 0xDF,
+
+0xA1, 0x1F, 0x4F, 0xE9,
+0xA2, 0x3F, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x06, 0x06, 0x1F, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x6C, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6B, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x69, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsa[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x8F, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x7B, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x21, 0x1A, 0xB0,
+0x25, 0x21, 0x31, 0xB0,
+
+0x0D, 0x21, 0x1A, 0xB2,
+0x05, 0x21, 0x31, 0xB2,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x05, 0x20,
+0x0D, 0x20,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x2F, 0xC0, 0x21, 0xC0,
+
+0x16, 0x42, 0x56, 0x9F,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x21, 0x31, 0xB4,
+0x2D, 0x21, 0x1A, 0xB4,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0x05,
+0x00, 0xE0,
+0x28, 0x19, 0x60, 0xEC,
+
+0x0D, 0x44, 0x4C, 0xB6,
+0x05, 0x44, 0x54, 0xB6,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x26, 0x1E, 0xDF,
+
+0xA7, 0x1E, 0x4F, 0xE9,
+0x17, 0x26, 0x16, 0xDF,
+
+0x2D, 0x20,
+0x00, 0xE0,
+0xA8, 0x3F, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x1E, 0xAF,
+0x25, 0x20,
+0x00, 0xE0,
+
+0xA4, 0x16, 0x4F, 0xE9,
+0x0F, 0xC0, 0x21, 0xC2,
+
+0xA6, 0x80, 0x4F, 0xE9,
+0x1F, 0x62, 0x57, 0x9F,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x00, 0x80, 0x00, 0xE8,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0xE0,
+0x0F, 0x20,
+
+0x17, 0x50, 0x56, 0x9F,
+0xA5, 0x37, 0x4F, 0xE9,
+
+0x06, 0xC0, 0x21, 0xC4,
+0x0F, 0x17, 0x0F, 0xAF,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2F, 0xC0, 0x44, 0xC6,
+0xA3, 0x80, 0x4F, 0xE9,
+
+0x06, 0x20,
+0x00, 0xE0,
+0x1F, 0x26, 0x1F, 0xDF,
+
+0x17, 0x26, 0x17, 0xDF,
+0x9D, 0x17, 0x4F, 0xE9,
+
+0xA1, 0x1F, 0x4F, 0xE9,
+0xA2, 0x3F, 0x4F, 0xE9,
+
+0x06, 0x06, 0x1F, 0xAF,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x9E, 0x37, 0x4F, 0xE9,
+0x2F, 0x17, 0x2F, 0xAF,
+
+0xA0, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x9C, 0x80, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x68, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x67, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x65, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x62, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsaf[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x94, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x80, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x21, 0x1A, 0xB0,
+0x25, 0x21, 0x31, 0xB0,
+
+0x0D, 0x21, 0x1A, 0xB2,
+0x05, 0x21, 0x31, 0xB2,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x05, 0x20,
+0x0D, 0x20,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x2F, 0xC0, 0x21, 0xC0,
+
+0x16, 0x42, 0x56, 0x9F,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x21, 0x31, 0xB4,
+0x2D, 0x21, 0x1A, 0xB4,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0x05,
+0x00, 0xE0,
+0x28, 0x19, 0x60, 0xEC,
+
+0x0D, 0x21, 0x1A, 0xB6,
+0x05, 0x21, 0x31, 0xB6,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x26, 0x1E, 0xDF,
+
+0xA7, 0x1E, 0x4F, 0xE9,
+0x17, 0x26, 0x16, 0xDF,
+
+0x2D, 0x20,
+0x00, 0xE0,
+0xA8, 0x3F, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x1E, 0xAF,
+0x25, 0x20,
+0x00, 0xE0,
+
+0xA4, 0x16, 0x4F, 0xE9,
+0x0F, 0xC0, 0x21, 0xC2,
+
+0xA6, 0x80, 0x4F, 0xE9,
+0x1F, 0x62, 0x57, 0x9F,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x2F, 0xC0, 0x21, 0xC6,
+
+0x2D, 0x44, 0x4C, 0xB6,
+0x25, 0x44, 0x54, 0xB6,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0xE0,
+0x0F, 0x20,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x07, 0xC0, 0x44, 0xC6,
+
+0x17, 0x50, 0x56, 0x9F,
+0xA5, 0x37, 0x4F, 0xE9,
+
+0x06, 0xC0, 0x21, 0xC4,
+0x0F, 0x17, 0x0F, 0xAF,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x3E, 0x3D, 0x5D, 0x9F,
+0x00, 0xE0,
+0x07, 0x20,
+
+0x2F, 0x20,
+0x00, 0xE0,
+0xA3, 0x0F, 0x4F, 0xE9,
+
+0x06, 0x20,
+0x00, 0xE0,
+0x1F, 0x26, 0x1F, 0xDF,
+
+0x17, 0x26, 0x17, 0xDF,
+0xA1, 0x1F, 0x4F, 0xE9,
+
+0x1E, 0x26, 0x1E, 0xDF,
+0x9D, 0x1E, 0x4F, 0xE9,
+
+0x35, 0x17, 0x4F, 0xE9,
+0xA2, 0x3F, 0x4F, 0xE9,
+
+0x06, 0x06, 0x1F, 0xAF,
+0x39, 0x37, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x17, 0xAF,
+0x07, 0x07, 0x1E, 0xAF,
+
+0xA0, 0x80, 0x4F, 0xE9,
+0x9E, 0x3E, 0x4F, 0xE9,
+
+0x31, 0x80, 0x4F, 0xE9,
+0x9C, 0x80, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x63, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x62, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x60, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x5D, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsf[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x8F, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x7B, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x21, 0x1A, 0xB0,
+0x25, 0x21, 0x31, 0xB0,
+
+0x0D, 0x21, 0x1A, 0xB2,
+0x05, 0x21, 0x31, 0xB2,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x05, 0x20,
+0x0D, 0x20,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x2F, 0xC0, 0x21, 0xC0,
+
+0x16, 0x42, 0x56, 0x9F,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x21, 0x31, 0xB4,
+0x2D, 0x21, 0x1A, 0xB4,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0x05,
+0x00, 0xE0,
+0x28, 0x19, 0x60, 0xEC,
+
+0x0D, 0x21, 0x1A, 0xB6,
+0x05, 0x21, 0x31, 0xB6,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x26, 0x1E, 0xDF,
+
+0xA7, 0x1E, 0x4F, 0xE9,
+0x17, 0x26, 0x16, 0xDF,
+
+0x2D, 0x20,
+0x00, 0xE0,
+0xA8, 0x3F, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x1E, 0xAF,
+0x25, 0x20,
+0x00, 0xE0,
+
+0xA4, 0x16, 0x4F, 0xE9,
+0x0F, 0xC0, 0x21, 0xC2,
+
+0xA6, 0x80, 0x4F, 0xE9,
+0x1F, 0x62, 0x57, 0x9F,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x2F, 0xC0, 0x21, 0xC6,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0xE0,
+0x0F, 0x20,
+
+0x17, 0x50, 0x56, 0x9F,
+0xA5, 0x37, 0x4F, 0xE9,
+
+0x06, 0xC0, 0x21, 0xC4,
+0x0F, 0x17, 0x0F, 0xAF,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2F, 0x20,
+0x00, 0xE0,
+0xA3, 0x80, 0x4F, 0xE9,
+
+0x06, 0x20,
+0x00, 0xE0,
+0x1F, 0x26, 0x1F, 0xDF,
+
+0x17, 0x26, 0x17, 0xDF,
+0x35, 0x17, 0x4F, 0xE9,
+
+0xA1, 0x1F, 0x4F, 0xE9,
+0xA2, 0x3F, 0x4F, 0xE9,
+
+0x06, 0x06, 0x1F, 0xAF,
+0x39, 0x37, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x17, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x31, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x68, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x67, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x65, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x62, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g400_t2gz[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x78, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x69, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x25, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x9F, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xBE, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x7D, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gza[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x7C, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x6D, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x29, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x74, 0xC6,
+0x3D, 0xCF, 0x74, 0xC2,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x0F, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB4,
+0x02, 0x44, 0x64, 0xB4,
+
+0x2A, 0x44, 0x54, 0xB6,
+0x1A, 0x44, 0x64, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x9B, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xBA, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x79, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzaf[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x81, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x72, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x37, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x2E, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x0F, 0xCF, 0x74, 0xC6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x0F, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB4,
+0x02, 0x44, 0x64, 0xB4,
+
+0x2A, 0x44, 0x54, 0xB6,
+0x1A, 0x44, 0x64, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x3D, 0xCF, 0x75, 0xC6,
+0x00, 0x80, 0x00, 0xE8,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x45, 0x55, 0xB6,
+0x02, 0x45, 0x65, 0xB6,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x3D, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x96, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xB5, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x74, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzf[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x7D, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x6E, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0F, 0xCF, 0x75, 0xC6,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x28, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x31, 0x0F, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB4,
+0x02, 0x44, 0x64, 0xB4,
+
+0x2A, 0x45, 0x55, 0xB6,
+0x1A, 0x45, 0x65, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x9A, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xBB, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x78, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzs[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x85, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x76, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x0F, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x31, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x0A, 0x45, 0x55, 0xB0,
+0x02, 0x45, 0x65, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB2,
+0x1A, 0x45, 0x65, 0xB2,
+
+0x0A, 0x45, 0x55, 0xB4,
+0x02, 0x45, 0x65, 0xB4,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x20,
+0x1A, 0x20,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA7, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x92, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xB2, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x70, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsa[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x8A, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x7B, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x0F, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x36, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x0A, 0x45, 0x55, 0xB0,
+0x02, 0x45, 0x65, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB2,
+0x1A, 0x45, 0x65, 0xB2,
+
+0x0A, 0x45, 0x55, 0xB4,
+0x02, 0x45, 0x65, 0xB4,
+
+0x0F, 0xCF, 0x74, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB6,
+0x1A, 0x44, 0x64, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x8D, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xAD, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x6B, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsaf[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x8E, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x7F, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x0F, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x3A, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x0A, 0x45, 0x55, 0xB0,
+0x02, 0x45, 0x65, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB2,
+0x1A, 0x45, 0x65, 0xB2,
+
+0x0A, 0x45, 0x55, 0xB4,
+0x02, 0x45, 0x65, 0xB4,
+
+0x0F, 0xCF, 0x74, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB6,
+0x1A, 0x44, 0x64, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x45, 0x55, 0xB6,
+0x02, 0x45, 0x65, 0xB6,
+
+0x3D, 0xCF, 0x75, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x31, 0x3D, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x89, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xA9, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x67, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsf[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x8A, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x7B, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x0F, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x36, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x0A, 0x45, 0x55, 0xB0,
+0x02, 0x45, 0x65, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB2,
+0x1A, 0x45, 0x65, 0xB2,
+
+0x0A, 0x45, 0x55, 0xB4,
+0x02, 0x45, 0x65, 0xB4,
+
+0x0F, 0xCF, 0x75, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x31, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB6,
+0x1A, 0x45, 0x65, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x8D, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xAD, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x6B, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgz[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x58, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x4A, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x1D, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xAF, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xD6, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x9D, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgza[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x5C, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x4E, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x27, 0xCF, 0x74, 0xC6,
+0x3D, 0xCF, 0x74, 0xC2,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x20, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x27, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB4,
+0x02, 0x44, 0x54, 0xB4,
+
+0x2A, 0x44, 0x4C, 0xB6,
+0x1A, 0x44, 0x54, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xAB, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xD3, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x99, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzaf[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x61, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x53, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x37, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x26, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x27, 0xCF, 0x74, 0xC6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x27, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB4,
+0x02, 0x44, 0x54, 0xB4,
+
+0x2A, 0x44, 0x4C, 0xB6,
+0x1A, 0x44, 0x54, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x3D, 0xCF, 0x75, 0xC6,
+0x00, 0x80, 0x00, 0xE8,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x45, 0x4D, 0xB6,
+0x02, 0x45, 0x55, 0xB6,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x3D, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xA6, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xCD, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x94, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzf[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x5D, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x4F, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x27, 0xCF, 0x75, 0xC6,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x20, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x31, 0x27, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB4,
+0x02, 0x44, 0x54, 0xB4,
+
+0x2A, 0x45, 0x4D, 0xB6,
+0x1A, 0x45, 0x55, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xAA, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xD3, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x98, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzs[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x65, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x57, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x27, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x29, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x27, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x0A, 0x45, 0x4D, 0xB0,
+0x02, 0x45, 0x55, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB2,
+0x1A, 0x45, 0x55, 0xB2,
+
+0x0A, 0x45, 0x4D, 0xB4,
+0x02, 0x45, 0x55, 0xB4,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA7, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xA2, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xCA, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x90, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsa[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x6A, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x5C, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x27, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x2E, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x27, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x0A, 0x45, 0x4D, 0xB0,
+0x02, 0x45, 0x55, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB2,
+0x1A, 0x45, 0x55, 0xB2,
+
+0x0A, 0x45, 0x4D, 0xB4,
+0x02, 0x45, 0x55, 0xB4,
+
+0x27, 0xCF, 0x74, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB6,
+0x1A, 0x44, 0x54, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0x9D, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xC5, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x8B, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsaf[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x6E, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x60, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x27, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x32, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x27, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x0A, 0x45, 0x4D, 0xB0,
+0x02, 0x45, 0x55, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB2,
+0x1A, 0x45, 0x55, 0xB2,
+
+0x0A, 0x45, 0x4D, 0xB4,
+0x02, 0x45, 0x55, 0xB4,
+
+0x27, 0xCF, 0x74, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB6,
+0x1A, 0x44, 0x54, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x45, 0x4D, 0xB6,
+0x02, 0x45, 0x55, 0xB6,
+
+0x3D, 0xCF, 0x75, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x31, 0x3D, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0x99, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xC1, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x87, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsf[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x6A, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x5C, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x27, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x2E, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x27, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x0A, 0x45, 0x4D, 0xB0,
+0x02, 0x45, 0x55, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB2,
+0x1A, 0x45, 0x55, 0xB2,
+
+0x0A, 0x45, 0x4D, 0xB4,
+0x02, 0x45, 0x55, 0xB4,
+
+0x27, 0xCF, 0x75, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x31, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB6,
+0x1A, 0x45, 0x55, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0x9D, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xC5, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x8B, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
diff --git a/sys/dev/drm/mga_warp.c b/sys/dev/drm/mga_warp.c
new file mode 100644
index 0000000..d2b8f20
--- /dev/null
+++ b/sys/dev/drm/mga_warp.c
@@ -0,0 +1,212 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/mga.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/mga_drv.h"
+#include "dev/drm/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 unsigned int mga_warp_g400_microcode_size( drm_mga_private_t *dev_priv )
+{
+ unsigned int size;
+
+ 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 ) );
+
+ size = PAGE_ALIGN( size );
+
+ DRM_DEBUG( "G400 ucode size = %d bytes\n", size );
+ return size;
+}
+
+static unsigned int mga_warp_g200_microcode_size( drm_mga_private_t *dev_priv )
+{
+ unsigned int size;
+
+ 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 ) );
+
+ size = PAGE_ALIGN( size );
+
+ DRM_DEBUG( "G200 ucode size = %d bytes\n", size );
+ return size;
+}
+
+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;
+ unsigned int size;
+
+ size = mga_warp_g400_microcode_size( dev_priv );
+ if ( size > dev_priv->warp->size ) {
+ DRM_ERROR( "microcode too large! (%u > %lu)\n",
+ size, dev_priv->warp->size );
+ DRM_OS_RETURN(ENOMEM);
+ }
+
+ 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;
+ unsigned int size;
+
+ size = mga_warp_g200_microcode_size( dev_priv );
+ if ( size > dev_priv->warp->size ) {
+ DRM_ERROR( "microcode too large! (%u > %lu)\n",
+ size, dev_priv->warp->size );
+ DRM_OS_RETURN(ENOMEM);
+ }
+
+ 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 )
+{
+ switch ( dev_priv->chipset ) {
+ case MGA_CARD_TYPE_G400:
+ return mga_warp_install_g400_microcode( dev_priv );
+ case MGA_CARD_TYPE_G200:
+ return mga_warp_install_g200_microcode( dev_priv );
+ default:
+ DRM_OS_RETURN(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:
+ 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:
+ DRM_OS_RETURN(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 );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ return 0;
+}
diff --git a/sys/dev/drm/r128.h b/sys/dev/drm/r128.h
new file mode 100644
index 0000000..8bcf10c
--- /dev/null
+++ b/sys/dev/drm/r128.h
@@ -0,0 +1,83 @@
+/* r128.h -- ATI Rage 128 DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 16:07:10 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __R128_H__
+#define __R128_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) r128_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP 1
+#define __MUST_HAVE_AGP 0
+#define __HAVE_MTRR 1
+#define __HAVE_CTX_BITMAP 1
+#define __HAVE_SG 1
+#define __HAVE_PCI_DMA 1
+
+/* Driver customization:
+ */
+#define DRIVER_PRERELEASE() do { \
+ if ( dev->dev_private ) { \
+ drm_r128_private_t *dev_priv = dev->dev_private; \
+ if ( dev_priv->page_flipping ) { \
+ r128_do_cleanup_pageflip( dev ); \
+ } \
+ } \
+} while (0)
+
+#define DRIVER_PRETAKEDOWN() do { \
+ if ( dev->dev_private ) r128_do_cleanup_cce( dev ); \
+} while (0)
+
+/* DMA customization:
+ */
+#define __HAVE_DMA 1
+
+#if 0
+/* GH: Remove this for now... */
+#define __HAVE_DMA_QUIESCENT 1
+#define DRIVER_DMA_QUIESCENT() do { \
+ drm_r128_private_t *dev_priv = dev->dev_private; \
+ return r128_do_cce_idle( dev_priv ); \
+} while (0)
+#endif
+
+/* Buffer customization:
+ */
+#define DRIVER_BUF_PRIV_T drm_r128_buf_priv_t
+
+#define DRIVER_AGP_BUFFERS_MAP( dev ) \
+ ((drm_r128_private_t *)((dev)->dev_private))->buffers
+
+#endif
diff --git a/sys/dev/drm/r128_cce.c b/sys/dev/drm/r128_cce.c
new file mode 100644
index 0000000..c6b5728
--- /dev/null
+++ b/sys/dev/drm/r128_cce.c
@@ -0,0 +1,1056 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#define __NO_VERSION__
+#include "dev/drm/r128.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/r128_drv.h"
+
+#ifdef __linux__
+#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
+#endif /* __linux__ */
+
+#define R128_FIFO_DEBUG 0
+
+int r128_do_wait_for_idle( drm_r128_private_t *dev_priv );
+
+/* 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
+};
+
+
+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_OS_DELAY( 1 );
+ }
+
+#if R128_FIFO_DEBUG
+ DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+#endif
+ DRM_OS_RETURN( 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_OS_DELAY( 1 );
+ }
+
+#if R128_FIFO_DEBUG
+ DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+#endif
+ DRM_OS_RETURN( EBUSY );
+}
+
+int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
+{
+ int i, ret;
+
+ ret = r128_do_wait_for_fifo( dev_priv, 64 );
+#ifdef __linux__
+ if ( ret < 0 ) return ret;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if ( ret ) return ret;
+#endif /* __FreeBSD__ */
+
+ 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_OS_DELAY( 1 );
+ }
+
+#if R128_FIFO_DEBUG
+ DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+#endif
+ DRM_OS_RETURN( 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( "%s\n", __FUNCTION__ );
+
+ 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->ring ) == 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_OS_DELAY( 1 );
+ }
+
+#if R128_FIFO_DEBUG
+ DRM_ERROR( "failed!\n" );
+ r128_status( dev_priv );
+#endif
+ DRM_OS_RETURN( 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_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 );
+ SET_RING_HEAD( &dev_priv->ring, 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 );
+
+ 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( "%s\n", __FUNCTION__ );
+
+ /* The manual (p. 2) says this address is in "VM space". This
+ * means it's an offset from the start of AGP space.
+ */
+#if __REALLY_HAVE_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 - dev->sg->handle;
+
+ 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 );
+
+ /* DL_RPTR_ADDR is a physical address in AGP space. */
+ SET_RING_HEAD( &dev_priv->ring, 0 );
+
+#if __REALLY_HAVE_SG
+ if ( !dev_priv->is_pci ) {
+#endif
+ R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
+ dev_priv->ring_rptr->offset );
+#if __REALLY_HAVE_SG
+ } else {
+ drm_sg_mem_t *entry = dev->sg;
+ unsigned long tmp_ofs, page_ofs;
+
+ tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+ page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+ R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
+ entry->busaddr[page_ofs]);
+ DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
+ entry->busaddr[page_ofs],
+ entry->handle + tmp_ofs );
+ }
+#endif
+
+ /* 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;
+#ifdef __linux__
+ struct list_head *list;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_map_list_entry_t *listentry;
+#endif /* __FreeBSD__ */
+
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
+ if ( dev_priv == NULL )
+ DRM_OS_RETURN( 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 );
+ DRM_OS_RETURN( 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 );
+ DRM_OS_RETURN( 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 );
+ DRM_OS_RETURN( 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));
+
+#ifdef __linux__
+ list_for_each(list, &dev->maplist->head) {
+ drm_map_list_t *r_list = (drm_map_list_t *)list;
+ if( r_list->map &&
+ r_list->map->type == _DRM_SHM &&
+ r_list->map->flags & _DRM_CONTAINS_LOCK ) {
+ dev_priv->sarea = r_list->map;
+ break;
+ }
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TAILQ_FOREACH(listentry, dev->maplist, link) {
+ drm_map_t *map = listentry->map;
+ if (map->type == _DRM_SHM &&
+ map->flags & _DRM_CONTAINS_LOCK) {
+ dev_priv->sarea = map;
+ break;
+ }
+ }
+#endif /* __FreeBSD__ */
+
+ if(!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+ if(!dev_priv->fb) {
+ DRM_ERROR("could not find framebuffer!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->mmio, 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 );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->cce_ring, 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 );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->ring_rptr, 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 );
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+ if(!dev_priv->buffers) {
+ DRM_ERROR("could not find dma buffer region!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ if ( !dev_priv->is_pci ) {
+ DRM_FIND_MAP( dev_priv->agp_textures,
+ 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 );
+ DRM_OS_RETURN(EINVAL);
+ }
+ }
+
+ dev_priv->sarea_priv =
+ (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ if ( !dev_priv->is_pci ) {
+ DRM_IOREMAP( dev_priv->cce_ring );
+ DRM_IOREMAP( dev_priv->ring_rptr );
+ DRM_IOREMAP( dev_priv->buffers );
+ if(!dev_priv->cce_ring->handle ||
+ !dev_priv->ring_rptr->handle ||
+ !dev_priv->buffers->handle) {
+ DRM_ERROR("Could not ioremap agp regions!\n");
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ } else {
+ dev_priv->cce_ring->handle =
+ (void *)dev_priv->cce_ring->offset;
+ dev_priv->ring_rptr->handle =
+ (void *)dev_priv->ring_rptr->offset;
+ dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+ }
+
+#if __REALLY_HAVE_AGP
+ if ( !dev_priv->is_pci )
+ dev_priv->cce_buffers_offset = dev->agp->base;
+ else
+#endif
+ dev_priv->cce_buffers_offset = dev->sg->handle;
+
+ dev_priv->ring.head = ((__volatile__ u32 *)
+ dev_priv->ring_rptr->handle);
+
+ 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 __REALLY_HAVE_SG
+ if ( dev_priv->is_pci ) {
+ if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
+ &dev_priv->bus_pci_gart) ) {
+ DRM_ERROR( "failed to init PCI GART!\n" );
+ dev->dev_private = (void *)dev_priv;
+ r128_do_cleanup_cce( dev );
+ DRM_OS_RETURN(ENOMEM);
+ }
+ R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
+ }
+#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 )
+{
+ if ( dev->dev_private ) {
+ drm_r128_private_t *dev_priv = dev->dev_private;
+
+#if __REALLY_HAVE_SG
+ if ( !dev_priv->is_pci ) {
+#endif
+ DRM_IOREMAPFREE( dev_priv->cce_ring );
+ DRM_IOREMAPFREE( dev_priv->ring_rptr );
+ DRM_IOREMAPFREE( dev_priv->buffers );
+#if __REALLY_HAVE_SG
+ } else {
+ if (!DRM(ati_pcigart_cleanup)( dev,
+ dev_priv->phys_pci_gart,
+ dev_priv->bus_pci_gart ))
+ DRM_ERROR( "failed to cleanup PCI GART!\n" );
+ }
+#endif
+
+ DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
+ DRM_MEM_DRIVER );
+ dev->dev_private = NULL;
+ }
+
+ return 0;
+}
+
+int r128_cce_init( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_init_t init;
+
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ DRM_OS_KRNFROMUSR( init, (drm_r128_init_t *)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 );
+ }
+
+ DRM_OS_RETURN( EINVAL );
+}
+
+int r128_cce_start( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ 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_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_cce_stop_t stop;
+ int ret;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR(stop, (drm_r128_cce_stop_t *)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 );
+#ifdef __linux__
+ if ( ret < 0 ) return ret;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if ( ret ) return ret;
+#endif /* __FreeBSD__ */
+ }
+
+ /* 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_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( !dev_priv ) {
+ DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
+ DRM_OS_RETURN( 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_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( dev_priv->cce_running ) {
+ r128_do_cce_flush( dev_priv );
+ }
+
+ return r128_do_cce_idle( dev_priv );
+}
+
+int r128_engine_reset( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ return r128_do_engine_reset( dev );
+}
+
+
+/* ================================================================
+ * Fullscreen mode
+ */
+
+static int r128_do_init_pageflip( drm_device_t *dev )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET );
+ dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
+
+ R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
+ R128_WRITE( R128_CRTC_OFFSET_CNTL,
+ dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
+
+ dev_priv->page_flipping = 1;
+ dev_priv->current_page = 0;
+
+ return 0;
+}
+
+int r128_do_cleanup_pageflip( drm_device_t *dev )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset );
+ R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
+
+ dev_priv->page_flipping = 0;
+ dev_priv->current_page = 0;
+
+ return 0;
+}
+
+int r128_fullscreen( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_fullscreen_t fs;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( fs, (drm_r128_fullscreen_t *)data, sizeof(fs) );
+
+ switch ( fs.func ) {
+ case R128_INIT_FULLSCREEN:
+ return r128_do_init_pageflip( dev );
+ case R128_CLEANUP_FULLSCREEN:
+ return r128_do_cleanup_pageflip( dev );
+ }
+
+ DRM_OS_RETURN( 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 )
+ DRM_OS_RETURN( 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 ) DRM_OS_RETURN( 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
+
+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->pid == 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_OS_DELAY( 1 );
+ }
+
+ DRM_ERROR( "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( ring );
+ if ( ring->space >= n )
+ return 0;
+ DRM_OS_DELAY( 1 );
+ }
+
+ /* FIXME: This is being ignored... */
+ DRM_ERROR( "failed!\n" );
+ DRM_OS_RETURN( EBUSY );
+}
+
+static int r128_cce_get_buffers( 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 ) DRM_OS_RETURN( EAGAIN );
+
+ buf->pid = DRM_OS_CURRENTPID;
+
+ if ( DRM_OS_COPYTOUSR( &d->request_indices[i], &buf->idx,
+ sizeof(buf->idx) ) )
+ DRM_OS_RETURN( EFAULT );
+ if ( DRM_OS_COPYTOUSR( &d->request_sizes[i], &buf->total,
+ sizeof(buf->total) ) )
+ DRM_OS_RETURN( EFAULT );
+ d->granted_count++;
+ }
+ return 0;
+}
+
+int r128_cce_buffers( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ int ret = 0;
+ drm_dma_t d;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( d, (drm_dma_t *) data, 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_OS_CURRENTPID, d.send_count );
+ DRM_OS_RETURN( 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_OS_CURRENTPID, d.request_count, dma->buf_count );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ d.granted_count = 0;
+
+ if ( d.request_count ) {
+ ret = r128_cce_get_buffers( dev, &d );
+ }
+
+ DRM_OS_KRNTOUSR((drm_dma_t *) data, d, sizeof(d) );
+
+ return ret;
+}
diff --git a/sys/dev/drm/r128_drm.h b/sys/dev/drm/r128_drm.h
new file mode 100644
index 0000000..9f50635
--- /dev/null
+++ b/sys/dev/drm/r128_drm.h
@@ -0,0 +1,289 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#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];
+ int tex_age[R128_NR_TEX_HEAPS];
+ int ctx_owner;
+} drm_r128_sarea_t;
+
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmR128.h)
+ */
+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 *x;
+ int *y;
+ unsigned int *buffer;
+ unsigned char *mask;
+} drm_r128_depth_t;
+
+typedef struct drm_r128_stipple {
+ unsigned int *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;
+
+#endif
diff --git a/sys/dev/drm/r128_drv.c b/sys/dev/drm/r128_drv.c
new file mode 100644
index 0000000..e6ce5fd
--- /dev/null
+++ b/sys/dev/drm/r128_drv.c
@@ -0,0 +1,167 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __linux__
+#include <linux/config.h>
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <pci/pcivar.h>
+#include <opt_drm_linux.h>
+#endif /* __FreeBSD__ */
+
+#include "dev/drm/r128.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/r128_drv.h"
+#if __REALLY_HAVE_SG
+#include "ati_pcigart.h"
+#endif
+
+#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME "r128"
+#define DRIVER_DESC "ATI Rage 128"
+#define DRIVER_DATE "20010405"
+
+#define DRIVER_MAJOR 2
+#define DRIVER_MINOR 2
+#define DRIVER_PATCHLEVEL 0
+
+#ifdef __FreeBSD__
+/* List acquired from xc/xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h
+ * Please report to eanholt@gladstone.uoregon.edu if your chip isn't
+ * represented in the list or if the information is incorrect.
+ */
+/* PCI cards are not supported with DRI under FreeBSD. */
+drm_chipinfo_t DRM(devicelist)[] = {
+ {0x1002, 0x4c45, 0, "ATI Rage 128 Mobility LE (PCI)"},
+ {0x1002, 0x4c46, 1, "ATI Rage 128 Mobility LF (AGP)"},
+ {0x1002, 0x4d46, 1, "ATI Rage 128 Mobility MF (AGP)"},
+ {0x1002, 0x4d4c, 1, "ATI Rage 128 Mobility ML (AGP)"},
+ {0x1002, 0x5044, 0, "ATI Rage 128 Pro PD (PCI)"},
+ {0x1002, 0x5046, 1, "ATI Rage 128 Pro PF (AGP)"},
+ {0x1002, 0x5050, 0, "ATI Rage 128 Pro PP (PCI)"},
+ {0x1002, 0x5052, 0, "ATI Rage 128 Pro PR (PCI)"},
+ {0x1002, 0x5245, 0, "ATI Rage 128 RE (PCI)"},
+ {0x1002, 0x5246, 1, "ATI Rage 128 RF (AGP)"},
+ {0x1002, 0x5247, 1, "ATI Rage 128 RG (AGP)"},
+ {0x1002, 0x524b, 0, "ATI Rage 128 RK (PCI)"},
+ {0x1002, 0x524c, 1, "ATI Rage 128 RL (AGP)"},
+ {0x1002, 0x534d, 1, "ATI Rage 128 SM (AGP)"},
+ {0x1002, 0x5446, 1, "ATI Rage 128 Pro Ultra TF (AGP)"},
+ {0x1002, 0x544C, 1, "ATI Rage 128 Pro Ultra TL (AGP)"},
+ {0x1002, 0x5452, 1, "ATI Rage 128 Pro Ultra TR (AGP)"},
+ {0, 0, 0, NULL}
+};
+#endif /* __FreeBSD__ */
+
+#define DRIVER_IOCTLS \
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { r128_cce_buffers, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)] = { r128_fullscreen, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 },
+
+
+#if 0
+/* GH: Count data sent to card via ring or vertex/indirect buffers.
+ */
+#define __HAVE_COUNTERS 3
+#define __HAVE_COUNTER6 _DRM_STAT_IRQ
+#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY
+#endif
+
+
+#include "dev/drm/drm_agpsupport.h"
+#include "dev/drm/drm_auth.h"
+#include "dev/drm/drm_bufs.h"
+#include "dev/drm/drm_context.h"
+#include "dev/drm/drm_dma.h"
+#include "dev/drm/drm_drawable.h"
+#include "dev/drm/drm_drv.h"
+
+#ifdef __linux__
+#ifndef MODULE
+/* DRM(options) is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO). It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+
+/* JH- We have to hand expand the string ourselves because of the cpp. If
+ * anyone can think of a way that we can fit into the __setup macro without
+ * changing it, then please send the solution my way.
+ */
+static int __init r128_options( char *str )
+{
+ DRM(parse_options)( str );
+ return 1;
+}
+
+__setup( DRIVER_NAME "=", r128_options );
+#endif
+#endif /* __linux__ */
+
+#include "dev/drm/drm_fops.h"
+#include "dev/drm/drm_init.h"
+#include "dev/drm/drm_ioctl.h"
+#include "dev/drm/drm_lock.h"
+#include "dev/drm/drm_memory.h"
+#ifdef __linux__
+#include "dev/drm/drm_proc.h"
+#include "dev/drm/drm_stub.h"
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include "dev/drm/drm_sysctl.h"
+#endif /* __FreeBSD__ */
+#include "dev/drm/drm_vm.h"
+#if __REALLY_HAVE_SG
+#include "dev/drm/drm_scatter.h"
+#endif
+
+#ifdef __FreeBSD__
+DRIVER_MODULE(r128, pci, r128_driver, r128_devclass, 0, 0);
+#endif /* __FreeBSD__ */
diff --git a/sys/dev/drm/r128_drv.h b/sys/dev/drm/r128_drv.h
new file mode 100644
index 0000000..7aacd48
--- /dev/null
+++ b/sys/dev/drm/r128_drv.h
@@ -0,0 +1,548 @@
+/* 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änzer <daenzerm@student.ethz.ch>
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __FreeBSD__
+#include <machine/endian.h>
+#if BYTE_ORDER==LITTLE_ENDIAN
+#define le32_to_cpu(x) x
+#define cpu_to_le32(x) x
+#else
+#define le32_to_cpu(x) ntohl(x)
+#define cpu_to_le32(x) htonl(x)
+#endif
+#endif /* __FreeBSD__ */
+
+#ifndef __R128_DRV_H__
+#define __R128_DRV_H__
+
+#define GET_RING_HEAD( ring ) le32_to_cpu( *(ring)->head )
+#define SET_RING_HEAD( ring, val ) *(ring)->head = cpu_to_le32( val )
+
+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;
+
+ volatile u32 *head;
+ 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 phys_pci_gart;
+#if __REALLY_HAVE_SG
+ dma_addr_t bus_pci_gart;
+#endif
+ 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_map_t *sarea;
+ drm_map_t *fb;
+ drm_map_t *mmio;
+ drm_map_t *cce_ring;
+ drm_map_t *ring_rptr;
+ drm_map_t *buffers;
+ drm_map_t *agp_textures;
+} 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;
+
+ /* r128_cce.c */
+extern int r128_cce_init( DRM_OS_IOCTL );
+extern int r128_cce_start( DRM_OS_IOCTL );
+extern int r128_cce_stop( DRM_OS_IOCTL );
+extern int r128_cce_reset( DRM_OS_IOCTL );
+extern int r128_cce_idle( DRM_OS_IOCTL );
+extern int r128_engine_reset( DRM_OS_IOCTL );
+extern int r128_fullscreen( DRM_OS_IOCTL );
+extern int r128_cce_buffers( DRM_OS_IOCTL );
+
+extern void r128_freelist_reset( drm_device_t *dev );
+extern drm_buf_t *r128_freelist_get( drm_device_t *dev );
+
+extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
+
+static __inline__ void
+r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring )
+{
+ ring->space = (GET_RING_HEAD( ring ) - ring->tail) * sizeof(u32);
+ if ( ring->space <= 0 )
+ ring->space += ring->size;
+}
+
+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_do_cleanup_pageflip( drm_device_t *dev );
+
+ /* r128_state.c */
+extern int r128_cce_clear( DRM_OS_IOCTL );
+extern int r128_cce_swap( DRM_OS_IOCTL );
+extern int r128_cce_vertex( DRM_OS_IOCTL );
+extern int r128_cce_indices( DRM_OS_IOCTL );
+extern int r128_cce_blit( DRM_OS_IOCTL );
+extern int r128_cce_depth( DRM_OS_IOCTL );
+extern int r128_cce_stipple( DRM_OS_IOCTL );
+extern int r128_cce_indirect( DRM_OS_IOCTL );
+
+
+/* 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_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_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_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_RGB8 9
+#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_BASE(reg) ((unsigned long)(dev_priv->mmio->handle))
+#define R128_ADDR(reg) (R128_BASE( reg ) + reg)
+
+#define R128_DEREF(reg) *(volatile u32 *)R128_ADDR( reg )
+#ifdef __alpha__
+#define R128_READ(reg) (_R128_READ((u32 *)R128_ADDR(reg)))
+static inline u32 _R128_READ(u32 *addr)
+{
+ DRM_OS_READMEMORYBARRIER;
+ return *(volatile u32 *)addr;
+}
+#define R128_WRITE(reg,val) \
+do { \
+ DRM_OS_WRITEMEMORYBARRIER; \
+ R128_DEREF(reg) = val; \
+} while (0)
+#else
+#define R128_READ(reg) le32_to_cpu( R128_DEREF( reg ) )
+#define R128_WRITE(reg,val) \
+do { \
+ R128_DEREF( reg ) = cpu_to_le32( val ); \
+} while (0)
+#endif
+
+#define R128_DEREF8(reg) *(volatile u8 *)R128_ADDR( reg )
+#ifdef __alpha__
+#define R128_READ8(reg) _R128_READ8((u8 *)R128_ADDR(reg))
+static inline u8 _R128_READ8(u8 *addr)
+{
+ DRM_OS_READMEMORYBARRIER;
+ return *(volatile u8 *)addr;
+}
+#define R128_WRITE8(reg,val) \
+do { \
+ DRM_OS_WRITEMEMORYBARRIER; \
+ R128_DEREF8(reg) = val; \
+} while (0)
+#else
+#define R128_READ8(reg) R128_DEREF8( reg )
+#define R128_WRITE8(reg,val) do { R128_DEREF8( reg ) = val; } while (0)
+#endif
+
+#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)
+
+extern int R128_READ_PLL(drm_device_t *dev, int addr);
+
+
+#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))
+
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+#define LOCK_TEST_WITH_RETURN( dev ) \
+do { \
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
+ dev->lock.pid != DRM_OS_CURRENTPID ) { \
+ DRM_ERROR( "%s called without lock held\n", \
+ __FUNCTION__ ); \
+ DRM_OS_RETURN( EINVAL ); \
+ } \
+} while (0)
+
+#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( ring ); \
+ if ( ring->space >= ring->high_mark ) \
+ goto __ring_space_done; \
+ DRM_OS_DELAY( 1 ); \
+ } \
+ DRM_ERROR( "ring space check failed!\n" ); \
+ DRM_OS_RETURN( 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 < 0 ) 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_flush_write_combine() DRM_OS_READMEMORYBARRIER
+
+
+#define R128_VERBOSE 0
+
+#define RING_LOCALS \
+ int write; 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) ) { \
+ r128_wait_ring( dev_priv, (n) * sizeof(u32) ); \
+ } \
+ 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) ); \
+ } \
+ r128_flush_write_combine(); \
+ dev_priv->ring.tail = write; \
+ R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write ); \
+} 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__ */
diff --git a/sys/dev/drm/r128_state.c b/sys/dev/drm/r128_state.c
new file mode 100644
index 0000000..d76f272
--- /dev/null
+++ b/sys/dev/drm/r128_state.c
@@ -0,0 +1,1576 @@
+/* r128_state.c -- State support for r128 -*- linux-c -*-
+ * Created: Thu Jan 27 02:53:43 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __linux__
+#define __NO_VERSION__
+#include <linux/delay.h>
+#endif /* __linux__ */
+
+#include "dev/drm/r128.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/r128_drv.h"
+#include "dev/drm/drm.h"
+
+
+
+/* ================================================================
+ * CCE hardware state programming functions
+ */
+
+static void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
+ drm_clip_rect_t *boxes, int count )
+{
+ u32 aux_sc_cntl = 0x00000000;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 17 );
+
+ if ( count >= 1 ) {
+ OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
+ OUT_RING( boxes[0].x1 );
+ OUT_RING( boxes[0].x2 - 1 );
+ OUT_RING( boxes[0].y1 );
+ OUT_RING( boxes[0].y2 - 1 );
+
+ aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
+ }
+ if ( count >= 2 ) {
+ OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) );
+ OUT_RING( boxes[1].x1 );
+ OUT_RING( boxes[1].x2 - 1 );
+ OUT_RING( boxes[1].y1 );
+ OUT_RING( boxes[1].y2 - 1 );
+
+ aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
+ }
+ if ( count >= 3 ) {
+ OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
+ OUT_RING( boxes[2].x1 );
+ OUT_RING( boxes[2].x2 - 1 );
+ OUT_RING( boxes[2].y1 );
+ OUT_RING( boxes[2].y2 - 1 );
+
+ aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
+ }
+
+ OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
+ OUT_RING( aux_sc_cntl );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_core( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
+ OUT_RING( ctx->scale_3d_cntl );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_context( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 13 );
+
+ OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
+ OUT_RING( ctx->dst_pitch_offset_c );
+ OUT_RING( ctx->dp_gui_master_cntl_c );
+ OUT_RING( ctx->sc_top_left_c );
+ OUT_RING( ctx->sc_bottom_right_c );
+ OUT_RING( ctx->z_offset_c );
+ OUT_RING( ctx->z_pitch_c );
+ OUT_RING( ctx->z_sten_cntl_c );
+ OUT_RING( ctx->tex_cntl_c );
+ OUT_RING( ctx->misc_3d_state_cntl_reg );
+ OUT_RING( ctx->texture_clr_cmp_clr_c );
+ OUT_RING( ctx->texture_clr_cmp_msk_c );
+ OUT_RING( ctx->fog_color_c );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_setup( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 3 );
+
+ OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
+ OUT_RING( ctx->setup_cntl );
+ OUT_RING( ctx->pm4_vc_fpu_setup );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_masks( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 5 );
+
+ OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
+ OUT_RING( ctx->dp_write_mask );
+
+ OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
+ OUT_RING( ctx->sten_ref_mask_c );
+ OUT_RING( ctx->plane_3d_mask_c );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_window( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
+ OUT_RING( ctx->window_xy_offset );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+ drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
+
+ OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
+ 2 + R128_MAX_TEXTURE_LEVELS ) );
+ OUT_RING( tex->tex_cntl );
+ OUT_RING( tex->tex_combine_cntl );
+ OUT_RING( ctx->tex_size_pitch_c );
+ for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
+ OUT_RING( tex->tex_offset[i] );
+ }
+
+ OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
+ OUT_RING( ctx->constant_color_c );
+ OUT_RING( tex->tex_border_color );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
+
+ OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
+ 1 + R128_MAX_TEXTURE_LEVELS ) );
+ OUT_RING( tex->tex_cntl );
+ OUT_RING( tex->tex_combine_cntl );
+ for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
+ OUT_RING( tex->tex_offset[i] );
+ }
+
+ OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
+ OUT_RING( tex->tex_border_color );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
+{
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+ DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
+
+ if ( dirty & R128_UPLOAD_CORE ) {
+ r128_emit_core( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_CORE;
+ }
+
+ if ( dirty & R128_UPLOAD_CONTEXT ) {
+ r128_emit_context( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
+ }
+
+ if ( dirty & R128_UPLOAD_SETUP ) {
+ r128_emit_setup( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
+ }
+
+ if ( dirty & R128_UPLOAD_MASKS ) {
+ r128_emit_masks( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
+ }
+
+ if ( dirty & R128_UPLOAD_WINDOW ) {
+ r128_emit_window( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
+ }
+
+ if ( dirty & R128_UPLOAD_TEX0 ) {
+ r128_emit_tex0( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
+ }
+
+ if ( dirty & R128_UPLOAD_TEX1 ) {
+ r128_emit_tex1( dev_priv );
+ sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
+ }
+
+ /* Turn off the texture cache flushing */
+ sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
+
+ sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
+}
+
+
+#if R128_PERFORMANCE_BOXES
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void r128_clear_box( drm_r128_private_t *dev_priv,
+ int x, int y, int w, int h,
+ int r, int g, int b )
+{
+ u32 pitch, offset;
+ u32 fb_bpp, color;
+ RING_LOCALS;
+
+ switch ( dev_priv->fb_bpp ) {
+ case 16:
+ fb_bpp = R128_GMC_DST_16BPP;
+ color = (((r & 0xf8) << 8) |
+ ((g & 0xfc) << 3) |
+ ((b & 0xf8) >> 3));
+ break;
+ case 24:
+ fb_bpp = R128_GMC_DST_24BPP;
+ color = ((r << 16) | (g << 8) | b);
+ break;
+ case 32:
+ fb_bpp = R128_GMC_DST_32BPP;
+ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ break;
+ default:
+ return;
+ }
+
+ offset = dev_priv->back_offset;
+ pitch = dev_priv->back_pitch >> 3;
+
+ BEGIN_RING( 6 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ fb_bpp |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS );
+
+ OUT_RING( (pitch << 21) | (offset >> 5) );
+ OUT_RING( color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+}
+
+static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv )
+{
+ if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
+ r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
+ } else {
+ atomic_set( &dev_priv->idle_count, 0 );
+ }
+}
+
+#endif
+
+
+/* ================================================================
+ * CCE command dispatch functions
+ */
+
+static void r128_print_dirty( const char *msg, unsigned int flags )
+{
+ DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & R128_UPLOAD_CORE) ? "core, " : "",
+ (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
+ (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
+ (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
+ (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
+ (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
+ (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
+ (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+ (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
+}
+
+static void r128_cce_dispatch_clear( drm_device_t *dev,
+ drm_r128_clear_t *clear )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ unsigned int flags = clear->flags;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
+ unsigned int tmp = flags;
+
+ flags &= ~(R128_FRONT | R128_BACK);
+ if ( tmp & R128_FRONT ) flags |= R128_BACK;
+ if ( tmp & R128_BACK ) flags |= R128_FRONT;
+ }
+
+ 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 & (R128_FRONT | R128_BACK) ) {
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
+ OUT_RING( clear->color_mask );
+
+ ADVANCE_RING();
+ }
+
+ if ( flags & R128_FRONT ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS );
+
+ OUT_RING( dev_priv->front_pitch_offset_c );
+ OUT_RING( clear->clear_color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+ }
+
+ if ( flags & R128_BACK ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS );
+
+ OUT_RING( dev_priv->back_pitch_offset_c );
+ OUT_RING( clear->clear_color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+ }
+
+ if ( flags & R128_DEPTH ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->depth_pitch_offset_c );
+ OUT_RING( clear->clear_depth );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+ }
+ }
+}
+
+static void r128_cce_dispatch_swap( drm_device_t *dev )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+#if R128_PERFORMANCE_BOXES
+ /* Do some trivial performance monitoring...
+ */
+ r128_cce_performance_boxes( dev_priv );
+#endif
+
+ 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;
+
+ BEGIN_RING( 7 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
+ OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+ R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (dev_priv->color_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_MEMORY |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->back_pitch_offset_c );
+ OUT_RING( dev_priv->front_pitch_offset_c );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+ }
+
+ /* Increment the frame counter. The client-side 3D driver must
+ * throttle the framerate by waiting for this value before
+ * performing the swapbuffer ioctl.
+ */
+ dev_priv->sarea_priv->last_frame++;
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
+ OUT_RING( dev_priv->sarea_priv->last_frame );
+
+ ADVANCE_RING();
+}
+
+static void r128_cce_dispatch_flip( drm_device_t *dev )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+ DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
+
+#if R128_PERFORMANCE_BOXES
+ /* Do some trivial performance monitoring...
+ */
+ r128_cce_performance_boxes( dev_priv );
+#endif
+
+ BEGIN_RING( 4 );
+
+ R128_WAIT_UNTIL_PAGE_FLIPPED();
+ OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 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;
+ }
+
+ ADVANCE_RING();
+
+ /* Increment the frame counter. The client-side 3D driver must
+ * throttle the framerate by waiting for this value before
+ * performing the swapbuffer ioctl.
+ */
+ dev_priv->sarea_priv->last_frame++;
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
+ OUT_RING( dev_priv->sarea_priv->last_frame );
+
+ ADVANCE_RING();
+}
+
+static void r128_cce_dispatch_vertex( drm_device_t *dev,
+ drm_buf_t *buf )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int format = sarea_priv->vc_format;
+ int offset = buf->bus_address;
+ int size = buf->used;
+ int prim = buf_priv->prim;
+ int i = 0;
+ RING_LOCALS;
+ DRM_DEBUG( "%s: buf=%d nbox=%d\n",
+ __FUNCTION__, buf->idx, sarea_priv->nbox );
+
+ if ( 0 )
+ r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
+
+ if ( buf->used ) {
+ buf_priv->dispatched = 1;
+
+ if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
+ r128_emit_state( dev_priv );
+ }
+
+ do {
+ /* Emit the next set of up to three cliprects */
+ if ( i < sarea_priv->nbox ) {
+ r128_emit_clip_rects( dev_priv,
+ &sarea_priv->boxes[i],
+ sarea_priv->nbox - i );
+ }
+
+ /* Emit the vertex buffer rendering commands */
+ BEGIN_RING( 5 );
+
+ OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+ OUT_RING( offset );
+ OUT_RING( size );
+ OUT_RING( format );
+ OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
+ (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
+
+ ADVANCE_RING();
+
+ i += 3;
+ } while ( i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
+ OUT_RING( buf_priv->age );
+
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ buf->used = 0;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+
+ sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
+ sarea_priv->nbox = 0;
+}
+
+static void r128_cce_dispatch_indirect( drm_device_t *dev,
+ drm_buf_t *buf,
+ int start, int end )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+ RING_LOCALS;
+ DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
+ buf->idx, start, end );
+
+ if ( start != end ) {
+ int offset = buf->bus_address + start;
+ int dwords = (end - start + 3) / sizeof(u32);
+
+ /* Indirect buffer data must be an even number of
+ * dwords, so if we've been given an odd number we must
+ * pad the data with a Type-2 CCE packet.
+ */
+ if ( dwords & 1 ) {
+ u32 *data = (u32 *)
+ ((char *)dev_priv->buffers->handle
+ + buf->offset + start);
+ data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
+ }
+
+ buf_priv->dispatched = 1;
+
+ /* Fire off the indirect buffer */
+ BEGIN_RING( 3 );
+
+ OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) );
+ OUT_RING( offset );
+ OUT_RING( dwords );
+
+ ADVANCE_RING();
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the indirect buffer age */
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
+ OUT_RING( buf_priv->age );
+
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ buf->used = 0;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+}
+
+static void r128_cce_dispatch_indices( drm_device_t *dev,
+ drm_buf_t *buf,
+ int start, int end,
+ int count )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int format = sarea_priv->vc_format;
+ int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
+ int prim = buf_priv->prim;
+ u32 *data;
+ int dwords;
+ int i = 0;
+ RING_LOCALS;
+ DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
+
+ if ( 0 )
+ r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
+
+ if ( start != end ) {
+ buf_priv->dispatched = 1;
+
+ if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
+ r128_emit_state( dev_priv );
+ }
+
+ dwords = (end - start + 3) / sizeof(u32);
+
+ data = (u32 *)((char *)dev_priv->buffers->handle
+ + buf->offset + start);
+
+ data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
+ dwords-2 ) );
+
+ data[1] = cpu_to_le32( offset );
+ data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
+ data[3] = cpu_to_le32( format );
+ data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
+ (count << 16)) );
+
+ if ( count & 0x1 ) {
+#ifdef __LITTLE_ENDIAN
+ data[dwords-1] &= 0x0000ffff;
+#else
+ data[dwords-1] &= 0xffff0000;
+#endif
+ }
+
+ do {
+ /* Emit the next set of up to three cliprects */
+ if ( i < sarea_priv->nbox ) {
+ r128_emit_clip_rects( dev_priv,
+ &sarea_priv->boxes[i],
+ sarea_priv->nbox - i );
+ }
+
+ r128_cce_dispatch_indirect( dev, buf, start, end );
+
+ i += 3;
+ } while ( i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
+ OUT_RING( buf_priv->age );
+
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+
+ sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
+ sarea_priv->nbox = 0;
+}
+
+static int r128_cce_dispatch_blit( drm_device_t *dev,
+ drm_r128_blit_t *blit, int pid )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_r128_buf_priv_t *buf_priv;
+ u32 *data;
+ int dword_shift, dwords;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ /* 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 R128_DATATYPE_ARGB8888:
+ dword_shift = 0;
+ break;
+ case R128_DATATYPE_ARGB1555:
+ case R128_DATATYPE_RGB565:
+ case R128_DATATYPE_ARGB4444:
+ dword_shift = 1;
+ break;
+ case R128_DATATYPE_CI8:
+ case R128_DATATYPE_RGB8:
+ dword_shift = 2;
+ break;
+ default:
+ DRM_ERROR( "invalid blit format %d\n", blit->format );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ /* Flush the pixel cache, and mark the contents as Read Invalid.
+ * This ensures no pixel data gets mixed up with the texture
+ * data from the host data blit, otherwise part of the texture
+ * image may be corrupted.
+ */
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
+ OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
+
+ ADVANCE_RING();
+
+ /* Dispatch the indirect buffer.
+ */
+ buf = dma->buflist[blit->idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != pid ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ pid, buf->pid );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", blit->idx );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ buf_priv->discard = 1;
+
+ dwords = (blit->width * blit->height) >> dword_shift;
+
+ data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+
+ data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
+ data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (blit->format << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_HOST_DATA |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_AUX_CLIP_DIS |
+ R128_GMC_WR_MSK_DIS) );
+
+ data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
+ data[3] = cpu_to_le32( 0xffffffff );
+ data[4] = cpu_to_le32( 0xffffffff );
+ data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
+ data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
+ data[7] = cpu_to_le32( dwords );
+
+ buf->used = (dwords + 8) * sizeof(u32);
+
+ r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
+
+ /* Flush the pixel cache after the blit completes. This ensures
+ * the texture data is written out to memory before rendering
+ * continues.
+ */
+ BEGIN_RING( 2 );
+
+ OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
+ OUT_RING( R128_PC_FLUSH_GUI );
+
+ ADVANCE_RING();
+
+ return 0;
+}
+
+
+/* ================================================================
+ * Tiled depth buffer management
+ *
+ * FIXME: These should all set the destination write mask for when we
+ * have hardware stencil support.
+ */
+
+static int r128_cce_dispatch_write_span( drm_device_t *dev,
+ drm_r128_depth_t *depth )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int count, x, y;
+ u32 *buffer;
+ u8 *mask;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ count = depth->n;
+ if ( DRM_OS_COPYFROMUSR( &x, depth->x, sizeof(x) ) ) {
+ DRM_OS_RETURN( EFAULT );
+ }
+ if ( DRM_OS_COPYFROMUSR( &y, depth->y, sizeof(y) ) ) {
+ DRM_OS_RETURN( EFAULT );
+ }
+
+ buffer = DRM_OS_MALLOC( depth->n * sizeof(u32) );
+ if ( buffer == NULL )
+ DRM_OS_RETURN( ENOMEM );
+ if ( DRM_OS_COPYFROMUSR( buffer, depth->buffer,
+ depth->n * sizeof(u32) ) ) {
+ DRM_OS_FREE( buffer );
+ DRM_OS_RETURN( EFAULT );
+ }
+
+ if ( depth->mask ) {
+ mask = DRM_OS_MALLOC( depth->n * sizeof(u8) );
+ if ( mask == NULL ) {
+ DRM_OS_FREE( buffer );
+ DRM_OS_RETURN( ENOMEM );
+ }
+ if ( DRM_OS_COPYFROMUSR( mask, depth->mask,
+ depth->n * sizeof(u8) ) ) {
+ DRM_OS_FREE( buffer );
+ DRM_OS_FREE( mask );
+ DRM_OS_RETURN( EFAULT );
+ }
+
+ for ( i = 0 ; i < count ; i++, x++ ) {
+ if ( mask[i] ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->depth_pitch_offset_c );
+ OUT_RING( buffer[i] );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (1 << 16) | 1 );
+
+ ADVANCE_RING();
+ }
+ }
+
+ DRM_OS_FREE( mask );
+ } else {
+ for ( i = 0 ; i < count ; i++, x++ ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->depth_pitch_offset_c );
+ OUT_RING( buffer[i] );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (1 << 16) | 1 );
+
+ ADVANCE_RING();
+ }
+ }
+
+ DRM_OS_FREE( buffer );
+
+ return 0;
+}
+
+static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
+ drm_r128_depth_t *depth )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int count, *x, *y;
+ u32 *buffer;
+ u8 *mask;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ count = depth->n;
+
+ x = DRM_OS_MALLOC( count * sizeof(*x) );
+ if ( x == NULL ) {
+ DRM_OS_RETURN( ENOMEM );
+ }
+ y = DRM_OS_MALLOC( count * sizeof(*y) );
+ if ( y == NULL ) {
+ DRM_OS_FREE( x );
+ DRM_OS_RETURN( ENOMEM );
+ }
+ if ( DRM_OS_COPYFROMUSR( x, depth->x, count * sizeof(int) ) ) {
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_RETURN( EFAULT );
+ }
+ if ( DRM_OS_COPYFROMUSR( y, depth->y, count * sizeof(int) ) ) {
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_RETURN( EFAULT );
+ }
+
+ buffer = DRM_OS_MALLOC( depth->n * sizeof(u32) );
+ if ( buffer == NULL ) {
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_RETURN( ENOMEM );
+ }
+ if ( DRM_OS_COPYFROMUSR( buffer, depth->buffer,
+ depth->n * sizeof(u32) ) ) {
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_FREE( buffer );
+ DRM_OS_RETURN( EFAULT );
+ }
+
+ if ( depth->mask ) {
+ mask = DRM_OS_MALLOC( depth->n * sizeof(u8) );
+ if ( mask == NULL ) {
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_FREE( buffer );
+ DRM_OS_RETURN( ENOMEM );
+ }
+ if ( DRM_OS_COPYFROMUSR( mask, depth->mask,
+ depth->n * sizeof(u8) ) ) {
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_FREE( buffer );
+ DRM_OS_FREE( mask );
+ DRM_OS_RETURN( EFAULT );
+ }
+
+ for ( i = 0 ; i < count ; i++ ) {
+ if ( mask[i] ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->depth_pitch_offset_c );
+ OUT_RING( buffer[i] );
+
+ OUT_RING( (x[i] << 16) | y[i] );
+ OUT_RING( (1 << 16) | 1 );
+
+ ADVANCE_RING();
+ }
+ }
+
+ DRM_OS_FREE( mask );
+ } else {
+ for ( i = 0 ; i < count ; i++ ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_P |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->depth_pitch_offset_c );
+ OUT_RING( buffer[i] );
+
+ OUT_RING( (x[i] << 16) | y[i] );
+ OUT_RING( (1 << 16) | 1 );
+
+ ADVANCE_RING();
+ }
+ }
+
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_FREE( buffer );
+
+ return 0;
+}
+
+static int r128_cce_dispatch_read_span( drm_device_t *dev,
+ drm_r128_depth_t *depth )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int count, x, y;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ count = depth->n;
+ if ( DRM_OS_COPYFROMUSR( &x, depth->x, sizeof(x) ) ) {
+ DRM_OS_RETURN( EFAULT );
+ }
+ if ( DRM_OS_COPYFROMUSR( &y, depth->y, sizeof(y) ) ) {
+ DRM_OS_RETURN( EFAULT );
+ }
+
+ BEGIN_RING( 7 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
+ OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+ R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_MEMORY |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->depth_pitch_offset_c );
+ OUT_RING( dev_priv->span_pitch_offset_c );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (0 << 16) | 0 );
+ OUT_RING( (count << 16) | 1 );
+
+ ADVANCE_RING();
+
+ return 0;
+}
+
+static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
+ drm_r128_depth_t *depth )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int count, *x, *y;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ count = depth->n;
+ if ( count > dev_priv->depth_pitch ) {
+ count = dev_priv->depth_pitch;
+ }
+
+ x = DRM_OS_MALLOC( count * sizeof(*x) );
+ if ( x == NULL ) {
+ DRM_OS_RETURN( ENOMEM );
+ }
+ y = DRM_OS_MALLOC( count * sizeof(*y) );
+ if ( y == NULL ) {
+ DRM_OS_FREE( x );
+ DRM_OS_RETURN( ENOMEM );
+ }
+ if ( DRM_OS_COPYFROMUSR( x, depth->x, count * sizeof(int) ) ) {
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_RETURN( EFAULT );
+ }
+ if ( DRM_OS_COPYFROMUSR( y, depth->y, count * sizeof(int) ) ) {
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+ DRM_OS_RETURN( EFAULT );
+ }
+
+ for ( i = 0 ; i < count ; i++ ) {
+ BEGIN_RING( 7 );
+
+ OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
+ OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+ R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (dev_priv->depth_fmt << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_MEMORY |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->depth_pitch_offset_c );
+ OUT_RING( dev_priv->span_pitch_offset_c );
+
+ OUT_RING( (x[i] << 16) | y[i] );
+ OUT_RING( (i << 16) | 0 );
+ OUT_RING( (1 << 16) | 1 );
+
+ ADVANCE_RING();
+ }
+
+ DRM_OS_FREE( x );
+ DRM_OS_FREE( y );
+
+ return 0;
+}
+
+
+/* ================================================================
+ * Polygon stipple
+ */
+
+static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
+{
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ BEGIN_RING( 33 );
+
+ OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
+ for ( i = 0 ; i < 32 ; i++ ) {
+ OUT_RING( stipple[i] );
+ }
+
+ ADVANCE_RING();
+}
+
+
+/* ================================================================
+ * IOCTL functions
+ */
+
+int r128_cce_clear( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_r128_clear_t clear;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( clear, (drm_r128_clear_t *) data,
+ sizeof(clear) );
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+ if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
+
+ r128_cce_dispatch_clear( dev, &clear );
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+
+ return 0;
+}
+
+int r128_cce_swap( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+ if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
+
+ if ( !dev_priv->page_flipping ) {
+ r128_cce_dispatch_swap( dev );
+ dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
+ R128_UPLOAD_MASKS);
+ } else {
+ r128_cce_dispatch_flip( dev );
+ }
+
+ return 0;
+}
+
+int r128_cce_vertex( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_r128_buf_priv_t *buf_priv;
+ drm_r128_vertex_t vertex;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ DRM_OS_KRNFROMUSR( vertex, (drm_r128_vertex_t *) data,
+ sizeof(vertex) );
+
+ DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n",
+ __FUNCTION__, DRM_OS_CURRENTPID,
+ vertex.idx, vertex.count, vertex.discard );
+
+ if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ vertex.idx, dma->buf_count - 1 );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( vertex.prim < 0 ||
+ vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
+ DRM_ERROR( "buffer prim %d\n", vertex.prim );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+ buf = dma->buflist[vertex.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != DRM_OS_CURRENTPID ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ buf->used = vertex.count;
+ buf_priv->prim = vertex.prim;
+ buf_priv->discard = vertex.discard;
+
+ r128_cce_dispatch_vertex( dev, buf );
+
+ return 0;
+}
+
+int r128_cce_indices( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_r128_buf_priv_t *buf_priv;
+ drm_r128_indices_t elts;
+ int count;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ DRM_OS_KRNFROMUSR( elts, (drm_r128_indices_t *) data,
+ sizeof(elts) );
+
+ DRM_DEBUG( "%s: pid=%d buf=%d s=%d e=%d d=%d\n",
+ __FUNCTION__, DRM_OS_CURRENTPID,
+ elts.idx, elts.start, elts.end, elts.discard );
+
+ if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ elts.idx, dma->buf_count - 1 );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( elts.prim < 0 ||
+ elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
+ DRM_ERROR( "buffer prim %d\n", elts.prim );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+ buf = dma->buflist[elts.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != DRM_OS_CURRENTPID ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", elts.idx );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ count = (elts.end - elts.start) / sizeof(u16);
+ elts.start -= R128_INDEX_PRIM_OFFSET;
+
+ if ( elts.start & 0x7 ) {
+ DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( elts.start < buf->used ) {
+ DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ buf->used = elts.end;
+ buf_priv->prim = elts.prim;
+ buf_priv->discard = elts.discard;
+
+ r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
+
+ return 0;
+}
+
+int r128_cce_blit( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_blit_t blit;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( blit, (drm_r128_blit_t *) data,
+ sizeof(blit) );
+
+ DRM_DEBUG( "%s: pid=%d index=%d\n",
+ __FUNCTION__, DRM_OS_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 );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+ return r128_cce_dispatch_blit( dev, &blit, DRM_OS_CURRENTPID );
+}
+
+int r128_cce_depth( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_depth_t depth;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( depth, (drm_r128_depth_t *) data,
+ sizeof(depth) );
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+ switch ( depth.func ) {
+ case R128_WRITE_SPAN:
+ return r128_cce_dispatch_write_span( dev, &depth );
+ case R128_WRITE_PIXELS:
+ return r128_cce_dispatch_write_pixels( dev, &depth );
+ case R128_READ_SPAN:
+ return r128_cce_dispatch_read_span( dev, &depth );
+ case R128_READ_PIXELS:
+ return r128_cce_dispatch_read_pixels( dev, &depth );
+ }
+
+ DRM_OS_RETURN( EINVAL );
+}
+
+int r128_cce_stipple( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_r128_stipple_t stipple;
+ u32 mask[32];
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( stipple, (drm_r128_stipple_t *) data,
+ sizeof(stipple) );
+
+ if ( DRM_OS_COPYFROMUSR( &mask, stipple.mask,
+ 32 * sizeof(u32) ) )
+ DRM_OS_RETURN( EFAULT );
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+ r128_cce_dispatch_stipple( dev, mask );
+
+ return 0;
+}
+
+int r128_cce_indirect( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_r128_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_r128_buf_priv_t *buf_priv;
+ drm_r128_indirect_t indirect;
+#if 0
+ RING_LOCALS;
+#endif
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ DRM_OS_KRNFROMUSR( indirect, (drm_r128_indirect_t *) data,
+ sizeof(indirect) );
+
+ DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
+ indirect.idx, indirect.start,
+ indirect.end, indirect.discard );
+
+ if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ indirect.idx, dma->buf_count - 1 );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ buf = dma->buflist[indirect.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != DRM_OS_CURRENTPID ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid );
+ DRM_OS_RETURN(EINVAL);
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ if ( indirect.start < buf->used ) {
+ DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
+ indirect.start, buf->used );
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+ buf->used = indirect.end;
+ buf_priv->discard = indirect.discard;
+
+#if 0
+ /* Wait for the 3D stream to idle before the indirect buffer
+ * containing 2D acceleration commands is processed.
+ */
+ BEGIN_RING( 2 );
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ ADVANCE_RING();
+#endif
+
+ /* Dispatch the indirect buffer full of commands from the
+ * X server. This is insecure and is thus only available to
+ * privileged clients.
+ */
+ r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+
+ return 0;
+}
diff --git a/sys/dev/drm/radeon.h b/sys/dev/drm/radeon.h
new file mode 100644
index 0000000..f30f069
--- /dev/null
+++ b/sys/dev/drm/radeon.h
@@ -0,0 +1,83 @@
+/* radeon.h -- ATI Radeon DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 17:07:34 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __RADEON_H__
+#define __RADEON_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) radeon_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP 1
+#define __MUST_HAVE_AGP 0
+#define __HAVE_MTRR 1
+#define __HAVE_CTX_BITMAP 1
+#define __HAVE_SG 1
+#define __HAVE_PCI_DMA 1
+
+/* Driver customization:
+ */
+#define DRIVER_PRERELEASE() do { \
+ if ( dev->dev_private ) { \
+ drm_radeon_private_t *dev_priv = dev->dev_private; \
+ if ( dev_priv->page_flipping ) { \
+ radeon_do_cleanup_pageflip( dev ); \
+ } \
+ } \
+} while (0)
+
+#define DRIVER_PRETAKEDOWN() do { \
+ if ( dev->dev_private ) radeon_do_cleanup_cp( dev ); \
+} while (0)
+
+/* DMA customization:
+ */
+#define __HAVE_DMA 1
+
+#if 0
+/* GH: Remove this for now... */
+#define __HAVE_DMA_QUIESCENT 1
+#define DRIVER_DMA_QUIESCENT() do { \
+ drm_radeon_private_t *dev_priv = dev->dev_private; \
+ return radeon_do_cp_idle( dev_priv ); \
+} while (0)
+#endif
+
+/* Buffer customization:
+ */
+#define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t
+
+#define DRIVER_AGP_BUFFERS_MAP( dev ) \
+ ((drm_radeon_private_t *)((dev)->dev_private))->buffers
+
+#endif
diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c
new file mode 100644
index 0000000..d69d3cd
--- /dev/null
+++ b/sys/dev/drm/radeon_cp.c
@@ -0,0 +1,1458 @@
+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * $FreeBSD$
+ */
+
+#include "dev/drm/radeon.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/radeon_drv.h"
+
+#ifdef __linux__
+#define __NO_VERSION__
+#include <linux/interrupt.h> /* For task queue support */
+#include <linux/delay.h>
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#endif /* __FreeBSD__ */
+
+#define RADEON_FIFO_DEBUG 0
+
+#if defined(__alpha__)
+# define PCIGART_ENABLED
+#else
+# undef PCIGART_ENABLED
+#endif
+
+
+/* CP microcode (from ATI) */
+static u32 radeon_cp_microcode[][2] = {
+ { 0x21007000, 0000000000 },
+ { 0x20007000, 0000000000 },
+ { 0x000000b4, 0x00000004 },
+ { 0x000000b8, 0x00000004 },
+ { 0x6f5b4d4c, 0000000000 },
+ { 0x4c4c427f, 0000000000 },
+ { 0x5b568a92, 0000000000 },
+ { 0x4ca09c6d, 0000000000 },
+ { 0xad4c4c4c, 0000000000 },
+ { 0x4ce1af3d, 0000000000 },
+ { 0xd8afafaf, 0000000000 },
+ { 0xd64c4cdc, 0000000000 },
+ { 0x4cd10d10, 0000000000 },
+ { 0x000f0000, 0x00000016 },
+ { 0x362f242d, 0000000000 },
+ { 0x00000012, 0x00000004 },
+ { 0x000f0000, 0x00000016 },
+ { 0x362f282d, 0000000000 },
+ { 0x000380e7, 0x00000002 },
+ { 0x04002c97, 0x00000002 },
+ { 0x000f0001, 0x00000016 },
+ { 0x333a3730, 0000000000 },
+ { 0x000077ef, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x00000021, 0x0000001a },
+ { 0x00004000, 0x0000001e },
+ { 0x00061000, 0x00000002 },
+ { 0x00000021, 0x0000001a },
+ { 0x00004000, 0x0000001e },
+ { 0x00061000, 0x00000002 },
+ { 0x00000021, 0x0000001a },
+ { 0x00004000, 0x0000001e },
+ { 0x00000017, 0x00000004 },
+ { 0x0003802b, 0x00000002 },
+ { 0x040067e0, 0x00000002 },
+ { 0x00000017, 0x00000004 },
+ { 0x000077e0, 0x00000002 },
+ { 0x00065000, 0x00000002 },
+ { 0x000037e1, 0x00000002 },
+ { 0x040067e1, 0x00000006 },
+ { 0x000077e0, 0x00000002 },
+ { 0x000077e1, 0x00000002 },
+ { 0x000077e1, 0x00000006 },
+ { 0xffffffff, 0000000000 },
+ { 0x10000000, 0000000000 },
+ { 0x0003802b, 0x00000002 },
+ { 0x040067e0, 0x00000006 },
+ { 0x00007675, 0x00000002 },
+ { 0x00007676, 0x00000002 },
+ { 0x00007677, 0x00000002 },
+ { 0x00007678, 0x00000006 },
+ { 0x0003802c, 0x00000002 },
+ { 0x04002676, 0x00000002 },
+ { 0x00007677, 0x00000002 },
+ { 0x00007678, 0x00000006 },
+ { 0x0000002f, 0x00000018 },
+ { 0x0000002f, 0x00000018 },
+ { 0000000000, 0x00000006 },
+ { 0x00000030, 0x00000018 },
+ { 0x00000030, 0x00000018 },
+ { 0000000000, 0x00000006 },
+ { 0x01605000, 0x00000002 },
+ { 0x00065000, 0x00000002 },
+ { 0x00098000, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x64c0603e, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00080000, 0x00000016 },
+ { 0000000000, 0000000000 },
+ { 0x0400251d, 0x00000002 },
+ { 0x00007580, 0x00000002 },
+ { 0x00067581, 0x00000002 },
+ { 0x04002580, 0x00000002 },
+ { 0x00067581, 0x00000002 },
+ { 0x00000049, 0x00000004 },
+ { 0x00005000, 0000000000 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x0000750e, 0x00000002 },
+ { 0x00019000, 0x00000002 },
+ { 0x00011055, 0x00000014 },
+ { 0x00000055, 0x00000012 },
+ { 0x0400250f, 0x00000002 },
+ { 0x0000504f, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00007565, 0x00000002 },
+ { 0x00007566, 0x00000002 },
+ { 0x00000058, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x01e655b4, 0x00000002 },
+ { 0x4401b0e4, 0x00000002 },
+ { 0x01c110e4, 0x00000002 },
+ { 0x26667066, 0x00000018 },
+ { 0x040c2565, 0x00000002 },
+ { 0x00000066, 0x00000018 },
+ { 0x04002564, 0x00000002 },
+ { 0x00007566, 0x00000002 },
+ { 0x0000005d, 0x00000004 },
+ { 0x00401069, 0x00000008 },
+ { 0x00101000, 0x00000002 },
+ { 0x000d80ff, 0x00000002 },
+ { 0x0080006c, 0x00000008 },
+ { 0x000f9000, 0x00000002 },
+ { 0x000e00ff, 0x00000002 },
+ { 0000000000, 0x00000006 },
+ { 0x0000008f, 0x00000018 },
+ { 0x0000005b, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00007576, 0x00000002 },
+ { 0x00065000, 0x00000002 },
+ { 0x00009000, 0x00000002 },
+ { 0x00041000, 0x00000002 },
+ { 0x0c00350e, 0x00000002 },
+ { 0x00049000, 0x00000002 },
+ { 0x00051000, 0x00000002 },
+ { 0x01e785f8, 0x00000002 },
+ { 0x00200000, 0x00000002 },
+ { 0x0060007e, 0x0000000c },
+ { 0x00007563, 0x00000002 },
+ { 0x006075f0, 0x00000021 },
+ { 0x20007073, 0x00000004 },
+ { 0x00005073, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00007576, 0x00000002 },
+ { 0x00007577, 0x00000002 },
+ { 0x0000750e, 0x00000002 },
+ { 0x0000750f, 0x00000002 },
+ { 0x00a05000, 0x00000002 },
+ { 0x00600083, 0x0000000c },
+ { 0x006075f0, 0x00000021 },
+ { 0x000075f8, 0x00000002 },
+ { 0x00000083, 0x00000004 },
+ { 0x000a750e, 0x00000002 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x0020750f, 0x00000002 },
+ { 0x00600086, 0x00000004 },
+ { 0x00007570, 0x00000002 },
+ { 0x00007571, 0x00000002 },
+ { 0x00007572, 0x00000006 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00005000, 0x00000002 },
+ { 0x00a05000, 0x00000002 },
+ { 0x00007568, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x00000095, 0x0000000c },
+ { 0x00058000, 0x00000002 },
+ { 0x0c607562, 0x00000002 },
+ { 0x00000097, 0x00000004 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x00600096, 0x00000004 },
+ { 0x400070e5, 0000000000 },
+ { 0x000380e6, 0x00000002 },
+ { 0x040025c5, 0x00000002 },
+ { 0x000380e5, 0x00000002 },
+ { 0x000000a8, 0x0000001c },
+ { 0x000650aa, 0x00000018 },
+ { 0x040025bb, 0x00000002 },
+ { 0x000610ab, 0x00000018 },
+ { 0x040075bc, 0000000000 },
+ { 0x000075bb, 0x00000002 },
+ { 0x000075bc, 0000000000 },
+ { 0x00090000, 0x00000006 },
+ { 0x00090000, 0x00000002 },
+ { 0x000d8002, 0x00000006 },
+ { 0x00007832, 0x00000002 },
+ { 0x00005000, 0x00000002 },
+ { 0x000380e7, 0x00000002 },
+ { 0x04002c97, 0x00000002 },
+ { 0x00007820, 0x00000002 },
+ { 0x00007821, 0x00000002 },
+ { 0x00007800, 0000000000 },
+ { 0x01200000, 0x00000002 },
+ { 0x20077000, 0x00000002 },
+ { 0x01200000, 0x00000002 },
+ { 0x20007000, 0x00000002 },
+ { 0x00061000, 0x00000002 },
+ { 0x0120751b, 0x00000002 },
+ { 0x8040750a, 0x00000002 },
+ { 0x8040750b, 0x00000002 },
+ { 0x00110000, 0x00000002 },
+ { 0x000380e5, 0x00000002 },
+ { 0x000000c6, 0x0000001c },
+ { 0x000610ab, 0x00000018 },
+ { 0x844075bd, 0x00000002 },
+ { 0x000610aa, 0x00000018 },
+ { 0x840075bb, 0x00000002 },
+ { 0x000610ab, 0x00000018 },
+ { 0x844075bc, 0x00000002 },
+ { 0x000000c9, 0x00000004 },
+ { 0x804075bd, 0x00000002 },
+ { 0x800075bb, 0x00000002 },
+ { 0x804075bc, 0x00000002 },
+ { 0x00108000, 0x00000002 },
+ { 0x01400000, 0x00000002 },
+ { 0x006000cd, 0x0000000c },
+ { 0x20c07000, 0x00000020 },
+ { 0x000000cf, 0x00000012 },
+ { 0x00800000, 0x00000006 },
+ { 0x0080751d, 0x00000006 },
+ { 0000000000, 0000000000 },
+ { 0x0000775c, 0x00000002 },
+ { 0x00a05000, 0x00000002 },
+ { 0x00661000, 0x00000002 },
+ { 0x0460275d, 0x00000020 },
+ { 0x00004000, 0000000000 },
+ { 0x01e00830, 0x00000002 },
+ { 0x21007000, 0000000000 },
+ { 0x6464614d, 0000000000 },
+ { 0x69687420, 0000000000 },
+ { 0x00000073, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0x00005000, 0x00000002 },
+ { 0x000380d0, 0x00000002 },
+ { 0x040025e0, 0x00000002 },
+ { 0x000075e1, 0000000000 },
+ { 0x00000001, 0000000000 },
+ { 0x000380e0, 0x00000002 },
+ { 0x04002394, 0x00000002 },
+ { 0x00005000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0x00000008, 0000000000 },
+ { 0x00000004, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+ { 0000000000, 0000000000 },
+};
+
+
+int RADEON_READ_PLL(drm_device_t *dev, int addr)
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
+ return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+}
+
+#if RADEON_FIFO_DEBUG
+static void radeon_status( drm_radeon_private_t *dev_priv )
+{
+ printk( "%s:\n", __FUNCTION__ );
+ printk( "RBBM_STATUS = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) );
+ printk( "CP_RB_RTPR = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
+ printk( "CP_RB_WTPR = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
+ printk( "AIC_CNTL = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
+ printk( "AIC_STAT = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
+ printk( "AIC_PT_BASE = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
+ printk( "TLB_ADDR = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
+ printk( "TLB_DATA = 0x%08x\n",
+ (unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
+}
+#endif
+
+
+/* ================================================================
+ * Engine, FIFO control
+ */
+
+static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv )
+{
+ u32 tmp;
+ int i;
+
+ tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
+ tmp |= RADEON_RB2D_DC_FLUSH_ALL;
+ RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ if ( !(RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT )
+ & RADEON_RB2D_DC_BUSY) ) {
+ return 0;
+ }
+ DRM_OS_DELAY( 1 );
+ }
+
+#if RADEON_FIFO_DEBUG
+ DRM_ERROR( "failed!\n" );
+ radeon_status( dev_priv );
+#endif
+ DRM_OS_RETURN( EBUSY );
+}
+
+static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
+ int entries )
+{
+ int i;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
+ & RADEON_RBBM_FIFOCNT_MASK );
+ if ( slots >= entries ) return 0;
+ DRM_OS_DELAY( 1 );
+ }
+
+#if RADEON_FIFO_DEBUG
+ DRM_ERROR( "failed!\n" );
+ radeon_status( dev_priv );
+#endif
+ DRM_OS_RETURN( EBUSY );
+}
+
+static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
+{
+ int i, ret;
+
+ ret = radeon_do_wait_for_fifo( dev_priv, 64 );
+#ifdef __linux__
+ if ( ret < 0 ) return ret;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if ( ret ) return ret;
+#endif /* __FreeBSD__ */
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ if ( !(RADEON_READ( RADEON_RBBM_STATUS )
+ & RADEON_RBBM_ACTIVE) ) {
+ radeon_do_pixcache_flush( dev_priv );
+ return 0;
+ }
+ DRM_OS_DELAY( 1 );
+ }
+
+#if RADEON_FIFO_DEBUG
+ DRM_ERROR( "failed!\n" );
+ radeon_status( dev_priv );
+#endif
+ DRM_OS_RETURN( EBUSY );
+}
+
+
+/* ================================================================
+ * CP control, initialization
+ */
+
+/* Load the microcode for the CP */
+static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
+{
+ int i;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ radeon_do_wait_for_idle( dev_priv );
+
+ RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
+ for ( i = 0 ; i < 256 ; i++ ) {
+ RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
+ radeon_cp_microcode[i][1] );
+ RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
+ radeon_cp_microcode[i][0] );
+ }
+}
+
+/* Flush any pending commands to the CP. 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 radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+#if 0
+ u32 tmp;
+
+ tmp = RADEON_READ( RADEON_CP_RB_WPTR ) | (1 << 31);
+ RADEON_WRITE( RADEON_CP_RB_WPTR, tmp );
+#endif
+}
+
+/* Wait for the CP to go idle.
+ */
+int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
+{
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ BEGIN_RING( 6 );
+
+ RADEON_PURGE_CACHE();
+ RADEON_PURGE_ZCACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+
+ return radeon_do_wait_for_idle( dev_priv );
+}
+
+/* Start the Command Processor.
+ */
+static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
+{
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ radeon_do_wait_for_idle( dev_priv );
+
+ RADEON_WRITE( RADEON_CP_CSQ_CNTL, dev_priv->cp_mode );
+
+ dev_priv->cp_running = 1;
+
+ BEGIN_RING( 6 );
+
+ RADEON_PURGE_CACHE();
+ RADEON_PURGE_ZCACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+}
+
+/* Reset the Command Processor. This will not flush any pending
+ * commands, so you must wait for the CP command stream to complete
+ * before calling this routine.
+ */
+static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
+{
+ u32 cur_read_ptr;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+ RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+ *dev_priv->ring.head = cur_read_ptr;
+ dev_priv->ring.tail = cur_read_ptr;
+}
+
+/* Stop the Command Processor. This will not flush any pending
+ * commands, so you must flush the command stream and wait for the CP
+ * to go idle before calling this routine.
+ */
+static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
+
+ dev_priv->cp_running = 0;
+}
+
+/* Reset the engine. This will stop the CP if it is running.
+ */
+static int radeon_do_engine_reset( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ radeon_do_pixcache_flush( dev_priv );
+
+ clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
+ mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
+
+ RADEON_WRITE_PLL( RADEON_MCLK_CNTL, ( mclk_cntl |
+ RADEON_FORCEON_MCLKA |
+ RADEON_FORCEON_MCLKB |
+ RADEON_FORCEON_YCLKA |
+ RADEON_FORCEON_YCLKB |
+ RADEON_FORCEON_MC |
+ RADEON_FORCEON_AIC ) );
+
+ rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
+
+ RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset |
+ RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_SE |
+ RADEON_SOFT_RESET_RE |
+ RADEON_SOFT_RESET_PP |
+ RADEON_SOFT_RESET_E2 |
+ RADEON_SOFT_RESET_RB ) );
+ RADEON_READ( RADEON_RBBM_SOFT_RESET );
+ RADEON_WRITE( RADEON_RBBM_SOFT_RESET, ( rbbm_soft_reset &
+ ~( RADEON_SOFT_RESET_CP |
+ RADEON_SOFT_RESET_HI |
+ RADEON_SOFT_RESET_SE |
+ RADEON_SOFT_RESET_RE |
+ RADEON_SOFT_RESET_PP |
+ RADEON_SOFT_RESET_E2 |
+ RADEON_SOFT_RESET_RB ) ) );
+ RADEON_READ( RADEON_RBBM_SOFT_RESET );
+
+
+ RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl );
+ RADEON_WRITE( RADEON_CLOCK_CNTL_INDEX, clock_cntl_index );
+ RADEON_WRITE( RADEON_RBBM_SOFT_RESET, rbbm_soft_reset );
+
+ /* Reset the CP ring */
+ radeon_do_cp_reset( dev_priv );
+
+ /* The CP is no longer running after an engine reset */
+ dev_priv->cp_running = 0;
+
+ /* Reset any pending vertex, indirect buffers */
+ radeon_freelist_reset( dev );
+
+ return 0;
+}
+
+static void radeon_cp_init_ring_buffer( drm_device_t *dev,
+ drm_radeon_private_t *dev_priv )
+{
+ u32 ring_start, cur_read_ptr;
+ u32 tmp;
+
+ /* Initialize the memory controller */
+ RADEON_WRITE( RADEON_MC_FB_LOCATION,
+ (dev_priv->agp_vm_start - 1) & 0xffff0000 );
+
+ if ( !dev_priv->is_pci ) {
+ RADEON_WRITE( RADEON_MC_AGP_LOCATION,
+ (((dev_priv->agp_vm_start - 1 +
+ dev_priv->agp_size) & 0xffff0000) |
+ (dev_priv->agp_vm_start >> 16)) );
+ }
+
+#if __REALLY_HAVE_AGP
+ if ( !dev_priv->is_pci )
+ ring_start = (dev_priv->cp_ring->offset
+ - dev->agp->base
+ + dev_priv->agp_vm_start);
+ else
+#endif
+ ring_start = (dev_priv->cp_ring->offset
+ - dev->sg->handle
+ + dev_priv->agp_vm_start);
+
+ RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
+
+ /* Set the write pointer delay */
+ RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
+
+ /* Initialize the ring buffer's read and write pointers */
+ cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+ RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+ *dev_priv->ring.head = cur_read_ptr;
+ dev_priv->ring.tail = cur_read_ptr;
+
+#if __REALLY_HAVE_SG
+ if ( !dev_priv->is_pci ) {
+#endif
+ RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+ dev_priv->ring_rptr->offset );
+#if __REALLY_HAVE_SG
+ } else {
+ drm_sg_mem_t *entry = dev->sg;
+ unsigned long tmp_ofs, page_ofs;
+
+ tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+ page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+ RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+ entry->busaddr[page_ofs]);
+ DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
+ entry->busaddr[page_ofs],
+ entry->handle + tmp_ofs );
+ }
+#endif
+
+ /* Set ring buffer size */
+ RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
+
+ radeon_do_wait_for_idle( dev_priv );
+
+ /* Turn on bus mastering */
+ tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
+ RADEON_WRITE( RADEON_BUS_CNTL, tmp );
+
+ /* Sync everything up */
+ RADEON_WRITE( RADEON_ISYNC_CNTL,
+ (RADEON_ISYNC_ANY2D_IDLE3D |
+ RADEON_ISYNC_ANY3D_IDLE2D |
+ RADEON_ISYNC_WAIT_IDLEGUI |
+ RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
+}
+
+static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
+{
+ drm_radeon_private_t *dev_priv;
+#ifdef __linux__
+ struct list_head *list;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ drm_map_list_entry_t *listentry;
+#endif /* __FreeBSD__ */
+ u32 tmp;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
+ if ( dev_priv == NULL )
+ DRM_OS_RETURN( ENOMEM );
+
+ memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
+
+ dev_priv->is_pci = init->is_pci;
+
+#if !defined(PCIGART_ENABLED)
+ /* PCI support is not 100% working, so we disable it here.
+ */
+ if ( dev_priv->is_pci ) {
+ DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN( EINVAL );
+ }
+#endif
+
+ if ( dev_priv->is_pci && !dev->sg ) {
+ DRM_ERROR( "PCI GART memory not allocated!\n" );
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ dev_priv->usec_timeout = init->usec_timeout;
+ if ( dev_priv->usec_timeout < 1 ||
+ dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
+ DRM_DEBUG( "TIMEOUT problem!\n" );
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ dev_priv->cp_mode = init->cp_mode;
+
+ /* 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->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
+ ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
+ DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ switch ( init->fb_bpp ) {
+ case 16:
+ dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
+ break;
+ case 32:
+ default:
+ dev_priv->color_fmt = RADEON_COLOR_FORMAT_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 = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+ break;
+ case 32:
+ default:
+ dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+ break;
+ }
+ dev_priv->depth_offset = init->depth_offset;
+ dev_priv->depth_pitch = init->depth_pitch;
+
+ dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
+ (dev_priv->front_offset >> 10));
+ dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
+ (dev_priv->back_offset >> 10));
+ dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
+ (dev_priv->depth_offset >> 10));
+
+ /* Hardware state for depth clears. Remove this if/when we no
+ * longer clear the depth buffer with a 3D rectangle. Hard-code
+ * all values to prevent unwanted 3D state from slipping through
+ * and screwing with the clear operation.
+ */
+ dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
+ RADEON_Z_ENABLE |
+ (dev_priv->color_fmt << 10) |
+ RADEON_ZBLOCK16);
+
+ dev_priv->depth_clear.rb3d_zstencilcntl = (dev_priv->depth_fmt |
+ RADEON_Z_TEST_ALWAYS |
+ RADEON_STENCIL_TEST_ALWAYS |
+ RADEON_STENCIL_S_FAIL_KEEP |
+ RADEON_STENCIL_ZPASS_KEEP |
+ RADEON_STENCIL_ZFAIL_KEEP |
+ RADEON_Z_WRITE_ENABLE);
+
+ dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
+ RADEON_BFACE_SOLID |
+ RADEON_FFACE_SOLID |
+ RADEON_FLAT_SHADE_VTX_LAST |
+ RADEON_DIFFUSE_SHADE_FLAT |
+ RADEON_ALPHA_SHADE_FLAT |
+ RADEON_SPECULAR_SHADE_FLAT |
+ RADEON_FOG_SHADE_FLAT |
+ RADEON_VTX_PIX_CENTER_OGL |
+ RADEON_ROUND_MODE_TRUNC |
+ RADEON_ROUND_PREC_8TH_PIX);
+
+#ifdef __linux__
+ list_for_each(list, &dev->maplist->head) {
+ drm_map_list_t *r_list = (drm_map_list_t *)list;
+ if( r_list->map &&
+ r_list->map->type == _DRM_SHM &&
+ r_list->map->flags & _DRM_CONTAINS_LOCK ) {
+ dev_priv->sarea = r_list->map;
+ break;
+ }
+ }
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ TAILQ_FOREACH(listentry, dev->maplist, link) {
+ drm_map_t *map = listentry->map;
+ if (map->type == _DRM_SHM &&
+ map->flags & _DRM_CONTAINS_LOCK) {
+ dev_priv->sarea = map;
+ break;
+ }
+ }
+#endif /* __FreeBSD__ */
+
+ if(!dev_priv->sarea) {
+ DRM_ERROR("could not find sarea!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+ if(!dev_priv->fb) {
+ DRM_ERROR("could not find framebuffer!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+ if(!dev_priv->mmio) {
+ DRM_ERROR("could not find mmio region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
+ if(!dev_priv->cp_ring) {
+ DRM_ERROR("could not find cp ring region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+ if(!dev_priv->ring_rptr) {
+ DRM_ERROR("could not find ring read pointer!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(EINVAL);
+ }
+ DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+ if(!dev_priv->buffers) {
+ DRM_ERROR("could not find dma buffer region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(EINVAL);
+ }
+
+ if ( !dev_priv->is_pci ) {
+ DRM_FIND_MAP( dev_priv->agp_textures,
+ init->agp_textures_offset );
+ if(!dev_priv->agp_textures) {
+ DRM_ERROR("could not find agp texture region!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(EINVAL);
+ }
+ }
+
+ dev_priv->sarea_priv =
+ (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
+ init->sarea_priv_offset);
+
+ if ( !dev_priv->is_pci ) {
+ DRM_IOREMAP( dev_priv->cp_ring );
+ DRM_IOREMAP( dev_priv->ring_rptr );
+ DRM_IOREMAP( dev_priv->buffers );
+ if(!dev_priv->cp_ring->handle ||
+ !dev_priv->ring_rptr->handle ||
+ !dev_priv->buffers->handle) {
+ DRM_ERROR("could not find ioremap agp regions!\n");
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(EINVAL);
+ }
+ } else {
+ dev_priv->cp_ring->handle =
+ (void *)dev_priv->cp_ring->offset;
+ dev_priv->ring_rptr->handle =
+ (void *)dev_priv->ring_rptr->offset;
+ dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+
+ DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
+ dev_priv->cp_ring->handle );
+ DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
+ dev_priv->ring_rptr->handle );
+ DRM_DEBUG( "dev_priv->buffers->handle %p\n",
+ dev_priv->buffers->handle );
+ }
+
+
+ dev_priv->agp_size = init->agp_size;
+ dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
+#if __REALLY_HAVE_AGP
+ if ( !dev_priv->is_pci )
+ dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
+ - dev->agp->base
+ + dev_priv->agp_vm_start);
+ else
+#endif
+ dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
+ - dev->sg->handle
+ + dev_priv->agp_vm_start);
+
+ DRM_DEBUG( "dev_priv->agp_size %d\n",
+ dev_priv->agp_size );
+ DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",
+ dev_priv->agp_vm_start );
+ DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",
+ dev_priv->agp_buffers_offset );
+
+ dev_priv->ring.head = ((__volatile__ u32 *)
+ dev_priv->ring_rptr->handle);
+
+ dev_priv->ring.start = (u32 *)dev_priv->cp_ring->handle;
+ dev_priv->ring.end = ((u32 *)dev_priv->cp_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 = RADEON_RING_HIGH_MARK;
+
+#if 0
+ /* Initialize the scratch register pointer. This will cause
+ * the scratch register values to be written out to memory
+ * whenever they are updated.
+ * FIXME: This doesn't quite work yet, so we're disabling it
+ * for the release.
+ */
+ RADEON_WRITE( RADEON_SCRATCH_ADDR, (dev_priv->ring_rptr->offset +
+ RADEON_SCRATCH_REG_OFFSET) );
+ RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+#endif
+
+ dev_priv->scratch = ((__volatile__ u32 *)
+ dev_priv->ring_rptr->handle +
+ (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+
+ dev_priv->sarea_priv->last_frame = 0;
+ RADEON_WRITE( RADEON_LAST_FRAME_REG,
+ dev_priv->sarea_priv->last_frame );
+
+ dev_priv->sarea_priv->last_dispatch = 0;
+ RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
+ dev_priv->sarea_priv->last_dispatch );
+
+ dev_priv->sarea_priv->last_clear = 0;
+ RADEON_WRITE( RADEON_LAST_CLEAR_REG,
+ dev_priv->sarea_priv->last_clear );
+
+#if __REALLY_HAVE_SG
+ if ( dev_priv->is_pci ) {
+ if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
+ &dev_priv->bus_pci_gart)) {
+ DRM_ERROR( "failed to init PCI GART!\n" );
+ dev->dev_private = (void *)dev_priv;
+ radeon_do_cleanup_cp(dev);
+ DRM_OS_RETURN(ENOMEM);
+ }
+ /* Turn on PCI GART
+ */
+ tmp = RADEON_READ( RADEON_AIC_CNTL )
+ | RADEON_PCIGART_TRANSLATE_EN;
+ RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+
+ /* set PCI GART page-table base address
+ */
+ RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
+
+ /* set address range for PCI address translate
+ */
+ RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );
+ RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start
+ + dev_priv->agp_size - 1);
+
+ /* Turn off AGP aperture -- is this required for PCIGART?
+ */
+ RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
+ RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
+ } else {
+#endif
+ /* Turn off PCI GART
+ */
+ tmp = RADEON_READ( RADEON_AIC_CNTL )
+ & ~RADEON_PCIGART_TRANSLATE_EN;
+ RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+#if __REALLY_HAVE_SG
+ }
+#endif
+
+ radeon_cp_load_microcode( dev_priv );
+ radeon_cp_init_ring_buffer( dev, dev_priv );
+
+#if ROTATE_BUFS
+ dev_priv->last_buf = 0;
+#endif
+
+ dev->dev_private = (void *)dev_priv;
+
+ radeon_do_engine_reset( dev );
+
+ return 0;
+}
+
+int radeon_do_cleanup_cp( drm_device_t *dev )
+{
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( dev->dev_private ) {
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+#if __REALLY_HAVE_SG
+ if ( !dev_priv->is_pci ) {
+#endif
+ DRM_IOREMAPFREE( dev_priv->cp_ring );
+ DRM_IOREMAPFREE( dev_priv->ring_rptr );
+ DRM_IOREMAPFREE( dev_priv->buffers );
+#if __REALLY_HAVE_SG
+ } else {
+ if (!DRM(ati_pcigart_cleanup)( dev,
+ dev_priv->phys_pci_gart,
+ dev_priv->bus_pci_gart ))
+ DRM_ERROR( "failed to cleanup PCI GART!\n" );
+ }
+#endif
+
+ DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
+ DRM_MEM_DRIVER );
+ dev->dev_private = NULL;
+ }
+
+ return 0;
+}
+
+int radeon_cp_init( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_init_t init;
+
+ DRM_OS_KRNFROMUSR( init, (drm_radeon_init_t *) data, sizeof(init) );
+
+ switch ( init.func ) {
+ case RADEON_INIT_CP:
+ return radeon_do_init_cp( dev, &init );
+ case RADEON_CLEANUP_CP:
+ return radeon_do_cleanup_cp( dev );
+ }
+
+ DRM_OS_RETURN( EINVAL );
+}
+
+int radeon_cp_start( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( dev_priv->cp_running ) {
+ DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
+ return 0;
+ }
+ if ( dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS ) {
+ DRM_DEBUG( "%s called with bogus CP mode (%d)\n",
+ __FUNCTION__, dev_priv->cp_mode );
+ return 0;
+ }
+
+ radeon_do_cp_start( dev_priv );
+
+ return 0;
+}
+
+/* Stop the CP. The engine must have been idled before calling this
+ * routine.
+ */
+int radeon_cp_stop( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_cp_stop_t stop;
+ int ret;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( stop, (drm_radeon_cp_stop_t *) data, sizeof(stop) );
+
+ /* Flush any pending CP commands. This ensures any outstanding
+ * commands are exectuted by the engine before we turn it off.
+ */
+ if ( stop.flush ) {
+ radeon_do_cp_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 = radeon_do_cp_idle( dev_priv );
+#ifdef __linux__
+ if ( ret < 0 ) return ret;
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+ if ( ret ) return ret;
+#endif /* __FreeBSD__ */
+ }
+
+ /* Finally, we can turn off the CP. If the engine isn't idle,
+ * we will get some dropped triangles as they won't be fully
+ * rendered before the CP is shut down.
+ */
+ radeon_do_cp_stop( dev_priv );
+
+ /* Reset the engine */
+ radeon_do_engine_reset( dev );
+
+ return 0;
+}
+
+/* Just reset the CP ring. Called as part of an X Server engine reset.
+ */
+int radeon_cp_reset( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( !dev_priv ) {
+ DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ radeon_do_cp_reset( dev_priv );
+
+ /* The CP is no longer running after an engine reset */
+ dev_priv->cp_running = 0;
+
+ return 0;
+}
+
+int radeon_cp_idle( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ return radeon_do_cp_idle( dev_priv );
+}
+
+int radeon_engine_reset( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ return radeon_do_engine_reset( dev );
+}
+
+
+/* ================================================================
+ * Fullscreen mode
+ */
+
+static int radeon_do_init_pageflip( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ dev_priv->crtc_offset = RADEON_READ( RADEON_CRTC_OFFSET );
+ dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL );
+
+ RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset );
+ RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL,
+ dev_priv->crtc_offset_cntl |
+ RADEON_CRTC_OFFSET_FLIP_CNTL );
+
+ dev_priv->page_flipping = 1;
+ dev_priv->current_page = 0;
+
+ return 0;
+}
+
+int radeon_do_cleanup_pageflip( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->crtc_offset );
+ RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
+
+ dev_priv->page_flipping = 0;
+ dev_priv->current_page = 0;
+
+ return 0;
+}
+
+int radeon_fullscreen( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_fullscreen_t fs;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( fs, (drm_radeon_fullscreen_t *) data,
+ sizeof(fs) );
+
+ switch ( fs.func ) {
+ case RADEON_INIT_FULLSCREEN:
+ return radeon_do_init_pageflip( dev );
+ case RADEON_CLEANUP_FULLSCREEN:
+ return radeon_do_cleanup_pageflip( dev );
+ }
+
+ DRM_OS_RETURN( EINVAL );
+}
+
+
+/* ================================================================
+ * Freelist management
+ */
+#define RADEON_BUFFER_USED 0xffffffff
+#define RADEON_BUFFER_FREE 0
+
+#if 0
+static int radeon_freelist_init( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_radeon_freelist_t *entry;
+ int i;
+
+ dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t),
+ DRM_MEM_DRIVER );
+ if ( dev_priv->head == NULL )
+ DRM_OS_RETURN( ENOMEM );
+
+ memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) );
+ dev_priv->head->age = RADEON_BUFFER_USED;
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+
+ entry = DRM(alloc)( sizeof(drm_radeon_freelist_t),
+ DRM_MEM_DRIVER );
+ if ( !entry ) DRM_OS_RETURN( ENOMEM );
+
+ entry->age = RADEON_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
+
+drm_buf_t *radeon_freelist_get( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_buf_t *buf;
+ int i, t;
+#if ROTATE_BUFS
+ int start;
+#endif
+
+ /* FIXME: Optimize -- use freelist code */
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ buf = dma->buflist[i];
+ buf_priv = buf->dev_private;
+ if ( buf->pid == 0 ) {
+ DRM_DEBUG( " ret buf=%d last=%d pid=0\n",
+ buf->idx, dev_priv->last_buf );
+ return buf;
+ }
+ DRM_DEBUG( " skipping buf=%d pid=%d\n",
+ buf->idx, buf->pid );
+ }
+
+#if ROTATE_BUFS
+ if ( ++dev_priv->last_buf >= dma->buf_count )
+ dev_priv->last_buf = 0;
+ start = dev_priv->last_buf;
+#endif
+ for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
+#if 0
+ /* FIXME: Disable this for now */
+ u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH];
+#else
+ u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG );
+#endif
+#if ROTATE_BUFS
+ for ( i = start ; i < dma->buf_count ; i++ ) {
+#else
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+#endif
+ 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;
+ DRM_DEBUG( " ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age );
+ return buf;
+ }
+ DRM_DEBUG( " skipping buf=%d age=%d done=%d\n",
+ buf->idx, buf_priv->age,
+ done_age );
+#if ROTATE_BUFS
+ start = 0;
+#endif
+ }
+ DRM_OS_DELAY( 1 );
+ }
+
+ DRM_ERROR( "returning NULL!\n" );
+ return NULL;
+}
+
+void radeon_freelist_reset( drm_device_t *dev )
+{
+ drm_device_dma_t *dma = dev->dma;
+#if ROTATE_BUFS
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+#endif
+ int i;
+
+#if ROTATE_BUFS
+ dev_priv->last_buf = 0;
+#endif
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ drm_buf_t *buf = dma->buflist[i];
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+ buf_priv->age = 0;
+ }
+}
+
+
+/* ================================================================
+ * CP command submission
+ */
+
+int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
+{
+ drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
+ int i;
+
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+ radeon_update_ring_snapshot( ring );
+ if ( ring->space > n )
+ return 0;
+ DRM_OS_DELAY( 1 );
+ }
+
+ /* FIXME: This return value is ignored in the BEGIN_RING macro! */
+#if RADEON_FIFO_DEBUG
+ radeon_status( dev_priv );
+ DRM_ERROR( "failed!\n" );
+#endif
+ DRM_OS_RETURN( EBUSY );
+}
+
+static int radeon_cp_get_buffers( 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 = radeon_freelist_get( dev );
+ if ( !buf ) DRM_OS_RETURN( EAGAIN );
+
+ buf->pid = DRM_OS_CURRENTPID;
+
+ if (DRM_OS_COPYTOUSR( &d->request_indices[i], &buf->idx,
+ sizeof(buf->idx) ) )
+ DRM_OS_RETURN( EFAULT );
+ if (DRM_OS_COPYTOUSR( &d->request_sizes[i], &buf->total,
+ sizeof(buf->total) ) )
+ DRM_OS_RETURN( EFAULT );
+
+ d->granted_count++;
+ }
+ return 0;
+}
+
+int radeon_cp_buffers( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_device_dma_t *dma = dev->dma;
+ int ret = 0;
+ drm_dma_t d;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( d, (drm_dma_t *) data, 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_OS_CURRENTPID, d.send_count );
+ DRM_OS_RETURN( 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_OS_CURRENTPID, d.request_count, dma->buf_count );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ d.granted_count = 0;
+
+ if ( d.request_count ) {
+ ret = radeon_cp_get_buffers( dev, &d );
+ }
+
+ DRM_OS_KRNTOUSR( (drm_dma_t *) data, d, sizeof(d) );
+
+ return ret;
+}
diff --git a/sys/dev/drm/radeon_drm.h b/sys/dev/drm/radeon_drm.h
new file mode 100644
index 0000000..698b9a2
--- /dev/null
+++ b/sys/dev/drm/radeon_drm.h
@@ -0,0 +1,335 @@
+/* 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.
+ * 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>
+ *
+ * $FreeBSD$
+ */
+
+#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__
+
+/* What needs to be changed for the current vertex buffer?
+ */
+#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_ALL 0x0001ffff
+
+#define RADEON_FRONT 0x1
+#define RADEON_BACK 0x2
+#define RADEON_DEPTH 0x4
+
+/* 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_HOSTDATA_BLIT_OFFSET 32
+
+#define RADEON_SCRATCH_REG_OFFSET 32
+
+/* Keep these small for testing
+ */
+#define RADEON_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 RADEON_LOCAL_TEX_HEAP 0
+#define RADEON_AGP_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 11
+#define RADEON_MAX_TEXTURE_UNITS 3
+
+#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 */
+
+#ifdef TCL_ENABLE
+ /* TCL state */
+ radeon_color_regs_t se_tcl_material_emmissive; /* 0x2210 */
+ radeon_color_regs_t se_tcl_material_ambient;
+ radeon_color_regs_t se_tcl_material_diffuse;
+ radeon_color_regs_t se_tcl_material_specular;
+ unsigned int se_tcl_shininess;
+ unsigned int se_tcl_output_vtx_fmt;
+ unsigned int se_tcl_output_vtx_sel;
+ unsigned int se_tcl_matrix_select_0;
+ unsigned int se_tcl_matrix_select_1;
+ unsigned int se_tcl_ucp_vert_blend_ctl;
+ unsigned int se_tcl_texture_proc_ctl;
+ unsigned int se_tcl_light_model_ctl;
+ unsigned int se_tcl_per_light_ctl[4];
+#endif
+
+ /* Misc state */
+ unsigned int re_top_left; /* 0x26c0 */
+ unsigned int re_misc;
+} drm_radeon_context_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;
+
+#ifdef CUBIC_ENABLE
+ unsigned int pp_cubic_faces;
+ unsigned int pp_cubic_offset[5];
+#endif
+} drm_radeon_texture_regs_t;
+
+typedef struct {
+ unsigned char next, prev;
+ unsigned char in_use;
+ int age;
+} drm_radeon_tex_region_t;
+
+typedef struct {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex buffer.
+ */
+ 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_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+ int tex_age[RADEON_NR_TEX_HEAPS];
+ int ctx_owner;
+} drm_radeon_sarea_t;
+
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmRadeon.h)
+ */
+typedef struct drm_radeon_init {
+ enum {
+ RADEON_INIT_CP = 0x01,
+ RADEON_CLEANUP_CP = 0x02
+ } func;
+ unsigned long sarea_priv_offset;
+ int is_pci;
+ int cp_mode;
+ int agp_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;
+ unsigned long mmio_offset;
+ unsigned long ring_offset;
+ unsigned long ring_rptr_offset;
+ unsigned long buffers_offset;
+ unsigned long agp_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;
+ drm_radeon_clear_rect_t *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;
+
+typedef struct drm_radeon_tex_image {
+ unsigned int x, y; /* Blit coordinates */
+ unsigned int width, height;
+ const void *data;
+} drm_radeon_tex_image_t;
+
+typedef struct drm_radeon_texture {
+ int offset;
+ int pitch;
+ int format;
+ int width; /* Texture image coordinates */
+ int height;
+ drm_radeon_tex_image_t *image;
+} drm_radeon_texture_t;
+
+typedef struct drm_radeon_stipple {
+ unsigned int *mask;
+} drm_radeon_stipple_t;
+
+typedef struct drm_radeon_indirect {
+ int idx;
+ int start;
+ int end;
+ int discard;
+} drm_radeon_indirect_t;
+
+#endif
diff --git a/sys/dev/drm/radeon_drv.c b/sys/dev/drm/radeon_drv.c
new file mode 100644
index 0000000..dc9b083
--- /dev/null
+++ b/sys/dev/drm/radeon_drv.c
@@ -0,0 +1,165 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+
+#ifdef __linux__
+#include <linux/config.h>
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <pci/pcivar.h>
+#include <opt_drm_linux.h>
+#endif /* __FreeBSD__ */
+
+#include "dev/drm/radeon.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/radeon_drv.h"
+#if __REALLY_HAVE_SG
+#include "ati_pcigart.h"
+#endif
+
+#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME "radeon"
+#define DRIVER_DESC "ATI Radeon"
+#define DRIVER_DATE "20010405"
+
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 1
+#define DRIVER_PATCHLEVEL 1
+
+#ifdef __FreeBSD__
+/* List acquired from xc/xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h
+ * Please report to eanholt@gladstone.uoregon.edu if your chip isn't
+ * represented in the list or if the information is incorrect.
+ */
+/* PCI cards are not supported with DRI under FreeBSD, and the 8500
+ * is not supported on any platform yet.
+ */
+drm_chipinfo_t DRM(devicelist)[] = {
+ {0x1002, 0x4242, 0, "ATI Radeon BB 8500 (AGP)"},
+ {0x1002, 0x4C57, 1, "ATI Radeon LW Mobility 7 (AGP)"},
+ {0x1002, 0x4C59, 1, "ATI Radeon LY Mobility 6 (AGP)"},
+ {0x1002, 0x4C5A, 1, "ATI Radeon LZ Mobility 6 (AGP)"},
+ {0x1002, 0x5144, 1, "ATI Radeon QD (AGP)"},
+ {0x1002, 0x5145, 1, "ATI Radeon QE (AGP)"},
+ {0x1002, 0x5146, 1, "ATI Radeon QF (AGP)"},
+ {0x1002, 0x5147, 1, "ATI Radeon QG (AGP)"},
+ {0x1002, 0x514C, 0, "ATI Radeon QL 8500 (AGP)"},
+ {0x1002, 0x514E, 0, "ATI Radeon QN 8500 (AGP)"},
+ {0x1002, 0x514F, 0, "ATI Radeon QO 8500 (AGP)"},
+ {0x1002, 0x5157, 1, "ATI Radeon QW 7500 (AGP)"},
+ {0x1002, 0x5159, 1, "ATI Radeon QY VE (AGP)"},
+ {0x1002, 0x515A, 1, "ATI Radeon QZ VE (AGP)"},
+ {0x1002, 0x516C, 0, "ATI Radeon Ql 8500 (AGP)"},
+ {0, 0, 0, NULL}
+};
+#endif /* __FreeBSD__ */
+
+#define DRIVER_IOCTLS \
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)] = { radeon_cp_start, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 },
+
+
+#if 0
+/* GH: Count data sent to card via ring or vertex/indirect buffers.
+ */
+#define __HAVE_COUNTERS 3
+#define __HAVE_COUNTER6 _DRM_STAT_IRQ
+#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY
+#endif
+
+
+#include "dev/drm/drm_agpsupport.h"
+#include "dev/drm/drm_auth.h"
+#include "dev/drm/drm_bufs.h"
+#include "dev/drm/drm_context.h"
+#include "dev/drm/drm_dma.h"
+#include "dev/drm/drm_drawable.h"
+#include "dev/drm/drm_drv.h"
+
+#ifdef __linux__
+#ifndef MODULE
+/* DRM(options) is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO). It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+
+/* JH- We have to hand expand the string ourselves because of the cpp. If
+ * anyone can think of a way that we can fit into the __setup macro without
+ * changing it, then please send the solution my way.
+ */
+static int __init radeon_options( char *str )
+{
+ DRM(parse_options)( str );
+ return 1;
+}
+
+__setup( DRIVER_NAME "=", radeon_options );
+#endif
+#endif /* __linux__ */
+
+#include "dev/drm/drm_fops.h"
+#include "dev/drm/drm_init.h"
+#include "dev/drm/drm_ioctl.h"
+#include "dev/drm/drm_lock.h"
+#include "dev/drm/drm_memory.h"
+#include "dev/drm/drm_vm.h"
+#ifdef __linux__
+#include "dev/drm/drm_proc.h"
+#include "dev/drm/drm_stub.h"
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include "dev/drm/drm_sysctl.h"
+#endif /* __FreeBSD__ */
+#if __REALLY_HAVE_SG
+#include "dev/drm/drm_scatter.h"
+#endif
+
+#ifdef __FreeBSD__
+DRIVER_MODULE(radeon, pci, radeon_driver, radeon_devclass, 0, 0);
+#endif /* __FreeBSD__ */
diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h
new file mode 100644
index 0000000..80f7a87
--- /dev/null
+++ b/sys/dev/drm/radeon_drv.h
@@ -0,0 +1,741 @@
+/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, 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:
+ * Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __RADEON_DRV_H__
+#define __RADEON_DRV_H__
+
+typedef struct drm_radeon_freelist {
+ unsigned int age;
+ drm_buf_t *buf;
+ struct drm_radeon_freelist *next;
+ struct drm_radeon_freelist *prev;
+} drm_radeon_freelist_t;
+
+typedef struct drm_radeon_ring_buffer {
+ u32 *start;
+ u32 *end;
+ int size;
+ int size_l2qw;
+
+ volatile u32 *head;
+ u32 tail;
+ u32 tail_mask;
+ int space;
+
+ int high_mark;
+} drm_radeon_ring_buffer_t;
+
+typedef struct drm_radeon_depth_clear_t {
+ u32 rb3d_cntl;
+ u32 rb3d_zstencilcntl;
+ u32 se_cntl;
+} drm_radeon_depth_clear_t;
+
+typedef struct drm_radeon_private {
+ drm_radeon_ring_buffer_t ring;
+ drm_radeon_sarea_t *sarea_priv;
+
+ int agp_size;
+ u32 agp_vm_start;
+ unsigned long agp_buffers_offset;
+
+ int cp_mode;
+ int cp_running;
+
+ drm_radeon_freelist_t *head;
+ drm_radeon_freelist_t *tail;
+/* FIXME: ROTATE_BUFS is a hask to cycle through bufs until freelist
+ code is used. Note this hides a problem with the scratch register
+ (used to keep track of last buffer completed) being written to before
+ the last buffer has actually completed rendering. */
+#define ROTATE_BUFS 1
+#if ROTATE_BUFS
+ int last_buf;
+#endif
+ volatile u32 *scratch;
+
+ int usec_timeout;
+ int is_pci;
+ unsigned long phys_pci_gart;
+#if __REALLY_HAVE_SG
+ dma_addr_t bus_pci_gart;
+#endif
+
+ 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;
+
+ u32 front_pitch_offset;
+ u32 back_pitch_offset;
+ u32 depth_pitch_offset;
+
+ drm_radeon_depth_clear_t depth_clear;
+
+ drm_map_t *sarea;
+ drm_map_t *fb;
+ drm_map_t *mmio;
+ drm_map_t *cp_ring;
+ drm_map_t *ring_rptr;
+ drm_map_t *buffers;
+ drm_map_t *agp_textures;
+} drm_radeon_private_t;
+
+typedef struct drm_radeon_buf_priv {
+ u32 age;
+ int prim;
+ int discard;
+ int dispatched;
+ drm_radeon_freelist_t *list_entry;
+} drm_radeon_buf_priv_t;
+
+ /* radeon_cp.c */
+extern int radeon_cp_init( DRM_OS_IOCTL );
+extern int radeon_cp_start( DRM_OS_IOCTL );
+extern int radeon_cp_stop( DRM_OS_IOCTL );
+extern int radeon_cp_reset( DRM_OS_IOCTL );
+extern int radeon_cp_idle( DRM_OS_IOCTL );
+extern int radeon_engine_reset( DRM_OS_IOCTL );
+extern int radeon_fullscreen( DRM_OS_IOCTL );
+extern int radeon_cp_buffers( DRM_OS_IOCTL );
+
+extern void radeon_freelist_reset( drm_device_t *dev );
+extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
+
+extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
+
+static __inline__ void
+radeon_update_ring_snapshot( drm_radeon_ring_buffer_t *ring )
+{
+ ring->space = (*(volatile int *)ring->head - ring->tail) * sizeof(u32);
+ if ( ring->space <= 0 )
+ ring->space += ring->size;
+}
+
+extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
+extern int radeon_do_cleanup_cp( drm_device_t *dev );
+extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
+
+ /* radeon_state.c */
+extern int radeon_cp_clear( DRM_OS_IOCTL );
+extern int radeon_cp_swap( DRM_OS_IOCTL );
+extern int radeon_cp_vertex( DRM_OS_IOCTL );
+extern int radeon_cp_indices( DRM_OS_IOCTL );
+extern int radeon_cp_texture( DRM_OS_IOCTL );
+extern int radeon_cp_stipple( DRM_OS_IOCTL );
+extern int radeon_cp_indirect( DRM_OS_IOCTL );
+
+/* Register definitions, register access macros and drmAddMap constants
+ * for Radeon kernel driver.
+ */
+
+#define RADEON_AGP_COMMAND 0x0f60
+#define RADEON_AUX_SCISSOR_CNTL 0x26f0
+# define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24)
+# define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25)
+# define RADEON_EXCLUSIVE_SCISSOR_2 (1 << 26)
+# define RADEON_SCISSOR_0_ENABLE (1 << 28)
+# define RADEON_SCISSOR_1_ENABLE (1 << 29)
+# define RADEON_SCISSOR_2_ENABLE (1 << 30)
+
+#define RADEON_BUS_CNTL 0x0030
+# define RADEON_BUS_MASTER_DIS (1 << 6)
+
+#define RADEON_CLOCK_CNTL_DATA 0x000c
+# define RADEON_PLL_WR_EN (1 << 7)
+#define RADEON_CLOCK_CNTL_INDEX 0x0008
+#define RADEON_CONFIG_APER_SIZE 0x0108
+#define RADEON_CRTC_OFFSET 0x0224
+#define RADEON_CRTC_OFFSET_CNTL 0x0228
+# define RADEON_CRTC_TILE_EN (1 << 15)
+# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16)
+
+#define RADEON_RB3D_COLORPITCH 0x1c48
+#define RADEON_RB3D_DEPTHCLEARVALUE 0x1c30
+#define RADEON_RB3D_DEPTHXY_OFFSET 0x1c60
+
+#define RADEON_DP_GUI_MASTER_CNTL 0x146c
+# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
+# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
+# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4)
+# define RADEON_GMC_BRUSH_NONE (15 << 4)
+# define RADEON_GMC_DST_16BPP (4 << 8)
+# define RADEON_GMC_DST_24BPP (5 << 8)
+# define RADEON_GMC_DST_32BPP (6 << 8)
+# define RADEON_GMC_DST_DATATYPE_SHIFT 8
+# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12)
+# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24)
+# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24)
+# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28)
+# define RADEON_GMC_WR_MSK_DIS (1 << 30)
+# define RADEON_ROP3_S 0x00cc0000
+# define RADEON_ROP3_P 0x00f00000
+#define RADEON_DP_WRITE_MASK 0x16cc
+#define RADEON_DST_PITCH_OFFSET 0x142c
+#define RADEON_DST_PITCH_OFFSET_C 0x1c80
+# define RADEON_DST_TILE_LINEAR (0 << 30)
+# define RADEON_DST_TILE_MACRO (1 << 30)
+# define RADEON_DST_TILE_MICRO (2 << 30)
+# define RADEON_DST_TILE_BOTH (3 << 30)
+
+#define RADEON_SCRATCH_REG0 0x15e0
+#define RADEON_SCRATCH_REG1 0x15e4
+#define RADEON_SCRATCH_REG2 0x15e8
+#define RADEON_SCRATCH_REG3 0x15ec
+#define RADEON_SCRATCH_REG4 0x15f0
+#define RADEON_SCRATCH_REG5 0x15f4
+#define RADEON_SCRATCH_UMSK 0x0770
+#define RADEON_SCRATCH_ADDR 0x0774
+
+#define RADEON_HOST_PATH_CNTL 0x0130
+# define RADEON_HDP_SOFT_RESET (1 << 26)
+# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
+# define RADEON_HDP_WC_TIMEOUT_28BCLK (7 << 28)
+
+#define RADEON_ISYNC_CNTL 0x1724
+# define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0)
+# define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1)
+# define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2)
+# define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3)
+# define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4)
+# define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5)
+
+#define RADEON_MC_AGP_LOCATION 0x014c
+#define RADEON_MC_FB_LOCATION 0x0148
+#define RADEON_MCLK_CNTL 0x0012
+# define RADEON_FORCEON_MCLKA (1 << 16)
+# define RADEON_FORCEON_MCLKB (1 << 17)
+# define RADEON_FORCEON_YCLKA (1 << 18)
+# define RADEON_FORCEON_YCLKB (1 << 19)
+# define RADEON_FORCEON_MC (1 << 20)
+# define RADEON_FORCEON_AIC (1 << 21)
+
+#define RADEON_PP_BORDER_COLOR_0 0x1d40
+#define RADEON_PP_BORDER_COLOR_1 0x1d44
+#define RADEON_PP_BORDER_COLOR_2 0x1d48
+#define RADEON_PP_CNTL 0x1c38
+# define RADEON_SCISSOR_ENABLE (1 << 1)
+#define RADEON_PP_LUM_MATRIX 0x1d00
+#define RADEON_PP_MISC 0x1c14
+#define RADEON_PP_ROT_MATRIX_0 0x1d58
+#define RADEON_PP_TXFILTER_0 0x1c54
+#define RADEON_PP_TXFILTER_1 0x1c6c
+#define RADEON_PP_TXFILTER_2 0x1c84
+
+#define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c
+# define RADEON_RB2D_DC_FLUSH (3 << 0)
+# define RADEON_RB2D_DC_FREE (3 << 2)
+# define RADEON_RB2D_DC_FLUSH_ALL 0xf
+# define RADEON_RB2D_DC_BUSY (1 << 31)
+#define RADEON_RB3D_CNTL 0x1c3c
+# define RADEON_ALPHA_BLEND_ENABLE (1 << 0)
+# define RADEON_PLANE_MASK_ENABLE (1 << 1)
+# define RADEON_DITHER_ENABLE (1 << 2)
+# define RADEON_ROUND_ENABLE (1 << 3)
+# define RADEON_SCALE_DITHER_ENABLE (1 << 4)
+# define RADEON_DITHER_INIT (1 << 5)
+# define RADEON_ROP_ENABLE (1 << 6)
+# define RADEON_STENCIL_ENABLE (1 << 7)
+# define RADEON_Z_ENABLE (1 << 8)
+# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9)
+# define RADEON_ZBLOCK8 (0 << 15)
+# define RADEON_ZBLOCK16 (1 << 15)
+#define RADEON_RB3D_DEPTHOFFSET 0x1c24
+#define RADEON_RB3D_PLANEMASK 0x1d84
+#define RADEON_RB3D_STENCILREFMASK 0x1d7c
+#define RADEON_RB3D_ZCACHE_MODE 0x3250
+#define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254
+# define RADEON_RB3D_ZC_FLUSH (1 << 0)
+# define RADEON_RB3D_ZC_FREE (1 << 2)
+# define RADEON_RB3D_ZC_FLUSH_ALL 0x5
+# define RADEON_RB3D_ZC_BUSY (1 << 31)
+#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
+# define RADEON_Z_TEST_MASK (7 << 4)
+# define RADEON_Z_TEST_ALWAYS (7 << 4)
+# define RADEON_STENCIL_TEST_ALWAYS (7 << 12)
+# define RADEON_STENCIL_S_FAIL_KEEP (0 << 16)
+# define RADEON_STENCIL_ZPASS_KEEP (0 << 20)
+# define RADEON_STENCIL_ZFAIL_KEEP (0 << 20)
+# define RADEON_Z_WRITE_ENABLE (1 << 30)
+#define RADEON_RBBM_SOFT_RESET 0x00f0
+# define RADEON_SOFT_RESET_CP (1 << 0)
+# define RADEON_SOFT_RESET_HI (1 << 1)
+# define RADEON_SOFT_RESET_SE (1 << 2)
+# define RADEON_SOFT_RESET_RE (1 << 3)
+# define RADEON_SOFT_RESET_PP (1 << 4)
+# define RADEON_SOFT_RESET_E2 (1 << 5)
+# define RADEON_SOFT_RESET_RB (1 << 6)
+# define RADEON_SOFT_RESET_HDP (1 << 7)
+#define RADEON_RBBM_STATUS 0x0e40
+# define RADEON_RBBM_FIFOCNT_MASK 0x007f
+# define RADEON_RBBM_ACTIVE (1 << 31)
+#define RADEON_RE_LINE_PATTERN 0x1cd0
+#define RADEON_RE_MISC 0x26c4
+#define RADEON_RE_TOP_LEFT 0x26c0
+#define RADEON_RE_WIDTH_HEIGHT 0x1c44
+#define RADEON_RE_STIPPLE_ADDR 0x1cc8
+#define RADEON_RE_STIPPLE_DATA 0x1ccc
+
+#define RADEON_SCISSOR_TL_0 0x1cd8
+#define RADEON_SCISSOR_BR_0 0x1cdc
+#define RADEON_SCISSOR_TL_1 0x1ce0
+#define RADEON_SCISSOR_BR_1 0x1ce4
+#define RADEON_SCISSOR_TL_2 0x1ce8
+#define RADEON_SCISSOR_BR_2 0x1cec
+#define RADEON_SE_COORD_FMT 0x1c50
+#define RADEON_SE_CNTL 0x1c4c
+# define RADEON_FFACE_CULL_CW (0 << 0)
+# define RADEON_BFACE_SOLID (3 << 1)
+# define RADEON_FFACE_SOLID (3 << 3)
+# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6)
+# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8)
+# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8)
+# define RADEON_ALPHA_SHADE_FLAT (1 << 10)
+# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10)
+# define RADEON_SPECULAR_SHADE_FLAT (1 << 12)
+# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12)
+# define RADEON_FOG_SHADE_FLAT (1 << 14)
+# define RADEON_FOG_SHADE_GOURAUD (2 << 14)
+# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24)
+# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25)
+# define RADEON_VTX_PIX_CENTER_OGL (1 << 27)
+# define RADEON_ROUND_MODE_TRUNC (0 << 28)
+# define RADEON_ROUND_PREC_8TH_PIX (1 << 30)
+#define RADEON_SE_CNTL_STATUS 0x2140
+#define RADEON_SE_LINE_WIDTH 0x1db8
+#define RADEON_SE_VPORT_XSCALE 0x1d98
+#define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8
+#define RADEON_SURFACE_ACCESS_CLR 0x0bfc
+#define RADEON_SURFACE_CNTL 0x0b00
+# define RADEON_SURF_TRANSLATION_DIS (1 << 8)
+# define RADEON_NONSURF_AP0_SWP_MASK (3 << 20)
+# define RADEON_NONSURF_AP0_SWP_LITTLE (0 << 20)
+# define RADEON_NONSURF_AP0_SWP_BIG16 (1 << 20)
+# define RADEON_NONSURF_AP0_SWP_BIG32 (2 << 20)
+# define RADEON_NONSURF_AP1_SWP_MASK (3 << 22)
+# define RADEON_NONSURF_AP1_SWP_LITTLE (0 << 22)
+# define RADEON_NONSURF_AP1_SWP_BIG16 (1 << 22)
+# define RADEON_NONSURF_AP1_SWP_BIG32 (2 << 22)
+#define RADEON_SURFACE0_INFO 0x0b0c
+# define RADEON_SURF_PITCHSEL_MASK (0x1ff << 0)
+# define RADEON_SURF_TILE_MODE_MASK (3 << 16)
+# define RADEON_SURF_TILE_MODE_MACRO (0 << 16)
+# define RADEON_SURF_TILE_MODE_MICRO (1 << 16)
+# define RADEON_SURF_TILE_MODE_32BIT_Z (2 << 16)
+# define RADEON_SURF_TILE_MODE_16BIT_Z (3 << 16)
+#define RADEON_SURFACE0_LOWER_BOUND 0x0b04
+#define RADEON_SURFACE0_UPPER_BOUND 0x0b08
+#define RADEON_SURFACE1_INFO 0x0b1c
+#define RADEON_SURFACE1_LOWER_BOUND 0x0b14
+#define RADEON_SURFACE1_UPPER_BOUND 0x0b18
+#define RADEON_SURFACE2_INFO 0x0b2c
+#define RADEON_SURFACE2_LOWER_BOUND 0x0b24
+#define RADEON_SURFACE2_UPPER_BOUND 0x0b28
+#define RADEON_SURFACE3_INFO 0x0b3c
+#define RADEON_SURFACE3_LOWER_BOUND 0x0b34
+#define RADEON_SURFACE3_UPPER_BOUND 0x0b38
+#define RADEON_SURFACE4_INFO 0x0b4c
+#define RADEON_SURFACE4_LOWER_BOUND 0x0b44
+#define RADEON_SURFACE4_UPPER_BOUND 0x0b48
+#define RADEON_SURFACE5_INFO 0x0b5c
+#define RADEON_SURFACE5_LOWER_BOUND 0x0b54
+#define RADEON_SURFACE5_UPPER_BOUND 0x0b58
+#define RADEON_SURFACE6_INFO 0x0b6c
+#define RADEON_SURFACE6_LOWER_BOUND 0x0b64
+#define RADEON_SURFACE6_UPPER_BOUND 0x0b68
+#define RADEON_SURFACE7_INFO 0x0b7c
+#define RADEON_SURFACE7_LOWER_BOUND 0x0b74
+#define RADEON_SURFACE7_UPPER_BOUND 0x0b78
+#define RADEON_SW_SEMAPHORE 0x013c
+
+#define RADEON_WAIT_UNTIL 0x1720
+# define RADEON_WAIT_CRTC_PFLIP (1 << 0)
+# define RADEON_WAIT_2D_IDLECLEAN (1 << 16)
+# define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
+# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
+
+#define RADEON_RB3D_ZMASKOFFSET 0x1c34
+#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
+# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
+# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0)
+
+
+/* CP registers */
+#define RADEON_CP_ME_RAM_ADDR 0x07d4
+#define RADEON_CP_ME_RAM_RADDR 0x07d8
+#define RADEON_CP_ME_RAM_DATAH 0x07dc
+#define RADEON_CP_ME_RAM_DATAL 0x07e0
+
+#define RADEON_CP_RB_BASE 0x0700
+#define RADEON_CP_RB_CNTL 0x0704
+#define RADEON_CP_RB_RPTR_ADDR 0x070c
+#define RADEON_CP_RB_RPTR 0x0710
+#define RADEON_CP_RB_WPTR 0x0714
+
+#define RADEON_CP_RB_WPTR_DELAY 0x0718
+# define RADEON_PRE_WRITE_TIMER_SHIFT 0
+# define RADEON_PRE_WRITE_LIMIT_SHIFT 23
+
+#define RADEON_CP_IB_BASE 0x0738
+
+#define RADEON_CP_CSQ_CNTL 0x0740
+# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0)
+# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28)
+# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28)
+# define RADEON_CSQ_PRIBM_INDDIS (2 << 28)
+# define RADEON_CSQ_PRIPIO_INDBM (3 << 28)
+# define RADEON_CSQ_PRIBM_INDBM (4 << 28)
+# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28)
+
+#define RADEON_AIC_CNTL 0x01d0
+# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
+#define RADEON_AIC_STAT 0x01d4
+#define RADEON_AIC_PT_BASE 0x01d8
+#define RADEON_AIC_LO_ADDR 0x01dc
+#define RADEON_AIC_HI_ADDR 0x01e0
+#define RADEON_AIC_TLB_ADDR 0x01e4
+#define RADEON_AIC_TLB_DATA 0x01e8
+
+/* CP command packets */
+#define RADEON_CP_PACKET0 0x00000000
+# define RADEON_ONE_REG_WR (1 << 15)
+#define RADEON_CP_PACKET1 0x40000000
+#define RADEON_CP_PACKET2 0x80000000
+#define RADEON_CP_PACKET3 0xC0000000
+# define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300
+# define RADEON_WAIT_FOR_IDLE 0x00002600
+# define RADEON_3D_DRAW_IMMD 0x00002900
+# define RADEON_3D_CLEAR_ZMASK 0x00003200
+# define RADEON_CNTL_HOSTDATA_BLT 0x00009400
+# define RADEON_CNTL_PAINT_MULTI 0x00009A00
+# define RADEON_CNTL_BITBLT_MULTI 0x00009B00
+
+#define RADEON_CP_PACKET_MASK 0xC0000000
+#define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000
+#define RADEON_CP_PACKET0_REG_MASK 0x000007ff
+#define RADEON_CP_PACKET1_REG0_MASK 0x000007ff
+#define RADEON_CP_PACKET1_REG1_MASK 0x003ff800
+
+#define RADEON_VTX_Z_PRESENT (1 << 31)
+
+#define RADEON_PRIM_TYPE_NONE (0 << 0)
+#define RADEON_PRIM_TYPE_POINT (1 << 0)
+#define RADEON_PRIM_TYPE_LINE (2 << 0)
+#define RADEON_PRIM_TYPE_LINE_STRIP (3 << 0)
+#define RADEON_PRIM_TYPE_TRI_LIST (4 << 0)
+#define RADEON_PRIM_TYPE_TRI_FAN (5 << 0)
+#define RADEON_PRIM_TYPE_TRI_STRIP (6 << 0)
+#define RADEON_PRIM_TYPE_TRI_TYPE2 (7 << 0)
+#define RADEON_PRIM_TYPE_RECT_LIST (8 << 0)
+#define RADEON_PRIM_TYPE_3VRT_POINT_LIST (9 << 0)
+#define RADEON_PRIM_TYPE_3VRT_LINE_LIST (10 << 0)
+#define RADEON_PRIM_WALK_IND (1 << 4)
+#define RADEON_PRIM_WALK_LIST (2 << 4)
+#define RADEON_PRIM_WALK_RING (3 << 4)
+#define RADEON_COLOR_ORDER_BGRA (0 << 6)
+#define RADEON_COLOR_ORDER_RGBA (1 << 6)
+#define RADEON_MAOS_ENABLE (1 << 7)
+#define RADEON_VTX_FMT_R128_MODE (0 << 8)
+#define RADEON_VTX_FMT_RADEON_MODE (1 << 8)
+#define RADEON_NUM_VERTICES_SHIFT 16
+
+#define RADEON_COLOR_FORMAT_CI8 2
+#define RADEON_COLOR_FORMAT_ARGB1555 3
+#define RADEON_COLOR_FORMAT_RGB565 4
+#define RADEON_COLOR_FORMAT_ARGB8888 6
+#define RADEON_COLOR_FORMAT_RGB332 7
+#define RADEON_COLOR_FORMAT_RGB8 9
+#define RADEON_COLOR_FORMAT_ARGB4444 15
+
+#define RADEON_TXFORMAT_I8 0
+#define RADEON_TXFORMAT_AI88 1
+#define RADEON_TXFORMAT_RGB332 2
+#define RADEON_TXFORMAT_ARGB1555 3
+#define RADEON_TXFORMAT_RGB565 4
+#define RADEON_TXFORMAT_ARGB4444 5
+#define RADEON_TXFORMAT_ARGB8888 6
+#define RADEON_TXFORMAT_RGBA8888 7
+
+/* Constants */
+#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
+
+#define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0
+#define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1
+#define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2
+#define RADEON_LAST_DISPATCH 1
+
+#define RADEON_MAX_VB_AGE 0x7fffffff
+#define RADEON_MAX_VB_VERTS (0xffff)
+
+#define RADEON_RING_HIGH_MARK 128
+
+
+#define RADEON_BASE(reg) ((unsigned long)(dev_priv->mmio->handle))
+#define RADEON_ADDR(reg) (RADEON_BASE( reg ) + reg)
+
+#define RADEON_DEREF(reg) *(volatile u32 *)RADEON_ADDR( reg )
+#ifdef __alpha__
+#define RADEON_READ(reg) (_RADEON_READ((u32 *)RADEON_ADDR( reg )))
+static inline u32 _RADEON_READ(u32 *addr)
+{
+ DRM_OS_READMEMORYBARRIER;
+ return *(volatile u32 *)addr;
+}
+#define RADEON_WRITE(reg,val) \
+do { \
+ DRM_OS_WRITEMEMORYBARRIER; \
+ RADEON_DEREF(reg) = val; \
+} while (0)
+#else
+#define RADEON_READ(reg) RADEON_DEREF( reg )
+#define RADEON_WRITE(reg, val) do { RADEON_DEREF( reg ) = val; } while (0)
+#endif
+
+#define RADEON_DEREF8(reg) *(volatile u8 *)RADEON_ADDR( reg )
+#ifdef __alpha__
+#define RADEON_READ8(reg) _RADEON_READ8((u8 *)RADEON_ADDR( reg ))
+static inline u8 _RADEON_READ8(u8 *addr)
+{
+ DRM_OS_READMEMORYBARRIER;
+ return *(volatile u8 *)addr;
+}
+#define RADEON_WRITE8(reg,val) \
+do { \
+ DRM_OS_WRITEMEMORYBARRIER; \
+ RADEON_DEREF8( reg ) = val; \
+} while (0)
+#else
+#define RADEON_READ8(reg) RADEON_DEREF8( reg )
+#define RADEON_WRITE8(reg, val) do { RADEON_DEREF8( reg ) = val; } while (0)
+#endif
+
+#define RADEON_WRITE_PLL( addr, val ) \
+do { \
+ RADEON_WRITE8( RADEON_CLOCK_CNTL_INDEX, \
+ ((addr) & 0x1f) | RADEON_PLL_WR_EN ); \
+ RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
+} while (0)
+
+extern int RADEON_READ_PLL( drm_device_t *dev, int addr );
+
+
+#define CP_PACKET0( reg, n ) \
+ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET0_TABLE( reg, n ) \
+ (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET1( reg0, reg1 ) \
+ (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2))
+#define CP_PACKET2() \
+ (RADEON_CP_PACKET2)
+#define CP_PACKET3( pkt, n ) \
+ (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
+
+
+/* ================================================================
+ * Engine control helper macros
+ */
+
+#define RADEON_WAIT_UNTIL_2D_IDLE() do { \
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
+ OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN) ); \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_3D_IDLE() do { \
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
+ OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN) ); \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_IDLE() do { \
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
+ OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \
+ RADEON_WAIT_3D_IDLECLEAN | \
+ RADEON_WAIT_HOST_IDLECLEAN) ); \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do { \
+ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \
+ OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \
+} while (0)
+
+#define RADEON_FLUSH_CACHE() do { \
+ OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
+ OUT_RING( RADEON_RB2D_DC_FLUSH ); \
+} while (0)
+
+#define RADEON_PURGE_CACHE() do { \
+ OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \
+ OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \
+} while (0)
+
+#define RADEON_FLUSH_ZCACHE() do { \
+ OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
+ OUT_RING( RADEON_RB3D_ZC_FLUSH ); \
+} while (0)
+
+#define RADEON_PURGE_ZCACHE() do { \
+ OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
+ OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
+} while (0)
+
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+#define LOCK_TEST_WITH_RETURN( dev ) \
+do { \
+ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
+ dev->lock.pid != DRM_OS_CURRENTPID ) { \
+ DRM_ERROR( "%s called without lock held\n", \
+ __FUNCTION__ ); \
+ DRM_OS_RETURN( EINVAL ); \
+ } \
+} while (0)
+
+#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
+do { \
+ drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; \
+ if ( ring->space < ring->high_mark ) { \
+ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \
+ radeon_update_ring_snapshot( ring ); \
+ if ( ring->space >= ring->high_mark ) \
+ goto __ring_space_done; \
+ DRM_OS_DELAY( 1 ); \
+ } \
+ DRM_ERROR( "ring space check failed!\n" ); \
+ DRM_OS_RETURN( EBUSY ); \
+ } \
+ __ring_space_done: \
+} while (0)
+
+#ifdef __linux__
+#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
+do { \
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \
+ if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
+ int __ret = radeon_do_cp_idle( dev_priv ); \
+ if ( __ret < 0 ) return __ret; \
+ sarea_priv->last_dispatch = 0; \
+ radeon_freelist_reset( dev ); \
+ } \
+} while (0)
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
+do { \
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \
+ if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
+ int __ret = radeon_do_cp_idle( dev_priv ); \
+ if ( __ret ) return __ret; \
+ sarea_priv->last_dispatch = 0; \
+ radeon_freelist_reset( dev ); \
+ } \
+} while (0)
+#endif /* __FreeBSD__ */
+
+#define RADEON_DISPATCH_AGE( age ) do { \
+ OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \
+ OUT_RING( age ); \
+} while (0)
+
+#define RADEON_FRAME_AGE( age ) do { \
+ OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \
+ OUT_RING( age ); \
+} while (0)
+
+#define RADEON_CLEAR_AGE( age ) do { \
+ OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \
+ OUT_RING( age ); \
+} while (0)
+
+
+/* ================================================================
+ * Ring control
+ */
+
+#define radeon_flush_write_combine() DRM_OS_READMEMORYBARRIER
+
+
+#define RADEON_VERBOSE 0
+
+#define RING_LOCALS int write; unsigned int mask; volatile u32 *ring;
+
+#define BEGIN_RING( n ) do { \
+ if ( RADEON_VERBOSE ) { \
+ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \
+ n, __FUNCTION__ ); \
+ } \
+ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
+ radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \
+ } \
+ dev_priv->ring.space -= (n) * sizeof(u32); \
+ ring = dev_priv->ring.start; \
+ write = dev_priv->ring.tail; \
+ mask = dev_priv->ring.tail_mask; \
+} while (0)
+
+#define ADVANCE_RING() do { \
+ if ( RADEON_VERBOSE ) { \
+ DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \
+ write, dev_priv->ring.tail ); \
+ } \
+ radeon_flush_write_combine(); \
+ dev_priv->ring.tail = write; \
+ RADEON_WRITE( RADEON_CP_RB_WPTR, write ); \
+} while (0)
+
+#define OUT_RING( x ) do { \
+ if ( RADEON_VERBOSE ) { \
+ DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \
+ (unsigned int)(x), write ); \
+ } \
+ ring[write++] = (x); \
+ write &= mask; \
+} while (0)
+
+#define RADEON_PERFORMANCE_BOXES 0
+
+#endif /* __RADEON_DRV_H__ */
diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c
new file mode 100644
index 0000000..ee3f834
--- /dev/null
+++ b/sys/dev/drm/radeon_state.c
@@ -0,0 +1,1467 @@
+/* radeon_state.c -- State support for Radeon -*- linux-c -*-
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __linux__
+#define __NO_VERSION__
+#include <linux/delay.h>
+#endif /* __linux__ */
+#include "dev/drm/radeon.h"
+#include "dev/drm/drmP.h"
+#include "dev/drm/radeon_drv.h"
+#include "dev/drm/drm.h"
+
+
+/* ================================================================
+ * CP hardware state programming functions
+ */
+
+static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
+ drm_clip_rect_t *box )
+{
+ RING_LOCALS;
+
+ DRM_DEBUG( " box: x1=%d y1=%d x2=%d y2=%d\n",
+ box->x1, box->y1, box->x2, box->y2 );
+
+ BEGIN_RING( 4 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
+ OUT_RING( (box->y1 << 16) | box->x1 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
+ OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_context( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 14 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
+ OUT_RING( ctx->pp_misc );
+ OUT_RING( ctx->pp_fog_color );
+ OUT_RING( ctx->re_solid_color );
+ OUT_RING( ctx->rb3d_blendcntl );
+ OUT_RING( ctx->rb3d_depthoffset );
+ OUT_RING( ctx->rb3d_depthpitch );
+ OUT_RING( ctx->rb3d_zstencilcntl );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
+ OUT_RING( ctx->pp_cntl );
+ OUT_RING( ctx->rb3d_cntl );
+ OUT_RING( ctx->rb3d_coloroffset );
+
+ OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
+ OUT_RING( ctx->rb3d_colorpitch );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_vertfmt( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
+ OUT_RING( ctx->se_coord_fmt );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_line( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 5 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
+ OUT_RING( ctx->re_line_pattern );
+ OUT_RING( ctx->re_line_state );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
+ OUT_RING( ctx->se_line_width );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_bumpmap( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 5 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
+ OUT_RING( ctx->pp_lum_matrix );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
+ OUT_RING( ctx->pp_rot_matrix_0 );
+ OUT_RING( ctx->pp_rot_matrix_1 );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_masks( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 4 );
+
+ OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
+ OUT_RING( ctx->rb3d_stencilrefmask );
+ OUT_RING( ctx->rb3d_ropcntl );
+ OUT_RING( ctx->rb3d_planemask );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_viewport( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 7 );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
+ OUT_RING( ctx->se_vport_xscale );
+ OUT_RING( ctx->se_vport_xoffset );
+ OUT_RING( ctx->se_vport_yscale );
+ OUT_RING( ctx->se_vport_yoffset );
+ OUT_RING( ctx->se_vport_zscale );
+ OUT_RING( ctx->se_vport_zoffset );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_setup( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 4 );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+ OUT_RING( ctx->se_cntl );
+ OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
+ OUT_RING( ctx->se_cntl_status );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_tcl( drm_radeon_private_t *dev_priv )
+{
+#ifdef TCL_ENABLE
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 29 );
+
+ OUT_RING( CP_PACKET0( RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 27 ) );
+ OUT_RING( ctx->se_tcl_material_emmissive.red );
+ OUT_RING( ctx->se_tcl_material_emmissive.green );
+ OUT_RING( ctx->se_tcl_material_emmissive.blue );
+ OUT_RING( ctx->se_tcl_material_emmissive.alpha );
+ OUT_RING( ctx->se_tcl_material_ambient.red );
+ OUT_RING( ctx->se_tcl_material_ambient.green );
+ OUT_RING( ctx->se_tcl_material_ambient.blue );
+ OUT_RING( ctx->se_tcl_material_ambient.alpha );
+ OUT_RING( ctx->se_tcl_material_diffuse.red );
+ OUT_RING( ctx->se_tcl_material_diffuse.green );
+ OUT_RING( ctx->se_tcl_material_diffuse.blue );
+ OUT_RING( ctx->se_tcl_material_diffuse.alpha );
+ OUT_RING( ctx->se_tcl_material_specular.red );
+ OUT_RING( ctx->se_tcl_material_specular.green );
+ OUT_RING( ctx->se_tcl_material_specular.blue );
+ OUT_RING( ctx->se_tcl_material_specular.alpha );
+ OUT_RING( ctx->se_tcl_shininess );
+ OUT_RING( ctx->se_tcl_output_vtx_fmt );
+ OUT_RING( ctx->se_tcl_output_vtx_sel );
+ OUT_RING( ctx->se_tcl_matrix_select_0 );
+ OUT_RING( ctx->se_tcl_matrix_select_1 );
+ OUT_RING( ctx->se_tcl_ucp_vert_blend_ctl );
+ OUT_RING( ctx->se_tcl_texture_proc_ctl );
+ OUT_RING( ctx->se_tcl_light_model_ctl );
+ for ( i = 0 ; i < 4 ; i++ ) {
+ OUT_RING( ctx->se_tcl_per_light_ctl[i] );
+ }
+
+ ADVANCE_RING();
+#else
+ DRM_ERROR( "TCL not enabled!\n" );
+#endif
+}
+
+static __inline__ void radeon_emit_misc( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 2 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
+ OUT_RING( ctx->re_misc );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_tex0( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[0];
+ RING_LOCALS;
+ DRM_DEBUG( " %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
+
+ BEGIN_RING( 9 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
+ OUT_RING( tex->pp_txfilter );
+ OUT_RING( tex->pp_txformat );
+ OUT_RING( tex->pp_txoffset );
+ OUT_RING( tex->pp_txcblend );
+ OUT_RING( tex->pp_txablend );
+ OUT_RING( tex->pp_tfactor );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
+ OUT_RING( tex->pp_border_color );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_tex1( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[1];
+ RING_LOCALS;
+ DRM_DEBUG( " %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
+
+ BEGIN_RING( 9 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
+ OUT_RING( tex->pp_txfilter );
+ OUT_RING( tex->pp_txformat );
+ OUT_RING( tex->pp_txoffset );
+ OUT_RING( tex->pp_txcblend );
+ OUT_RING( tex->pp_txablend );
+ OUT_RING( tex->pp_tfactor );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
+ OUT_RING( tex->pp_border_color );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_tex2( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[2];
+ RING_LOCALS;
+ DRM_DEBUG( " %s\n", __FUNCTION__ );
+
+ BEGIN_RING( 9 );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
+ OUT_RING( tex->pp_txfilter );
+ OUT_RING( tex->pp_txformat );
+ OUT_RING( tex->pp_txoffset );
+ OUT_RING( tex->pp_txcblend );
+ OUT_RING( tex->pp_txablend );
+ OUT_RING( tex->pp_tfactor );
+
+ OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
+ OUT_RING( tex->pp_border_color );
+
+ ADVANCE_RING();
+}
+
+static __inline__ void radeon_emit_state( drm_radeon_private_t *dev_priv )
+{
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ unsigned int dirty = sarea_priv->dirty;
+
+ DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
+
+ if ( dirty & RADEON_UPLOAD_CONTEXT ) {
+ radeon_emit_context( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_CONTEXT;
+ }
+
+ if ( dirty & RADEON_UPLOAD_VERTFMT ) {
+ radeon_emit_vertfmt( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_VERTFMT;
+ }
+
+ if ( dirty & RADEON_UPLOAD_LINE ) {
+ radeon_emit_line( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_LINE;
+ }
+
+ if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
+ radeon_emit_bumpmap( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_BUMPMAP;
+ }
+
+ if ( dirty & RADEON_UPLOAD_MASKS ) {
+ radeon_emit_masks( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_MASKS;
+ }
+
+ if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
+ radeon_emit_viewport( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_VIEWPORT;
+ }
+
+ if ( dirty & RADEON_UPLOAD_SETUP ) {
+ radeon_emit_setup( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_SETUP;
+ }
+
+ if ( dirty & RADEON_UPLOAD_TCL ) {
+#ifdef TCL_ENABLE
+ radeon_emit_tcl( dev_priv );
+#endif
+ sarea_priv->dirty &= ~RADEON_UPLOAD_TCL;
+ }
+
+ if ( dirty & RADEON_UPLOAD_MISC ) {
+ radeon_emit_misc( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_MISC;
+ }
+
+ if ( dirty & RADEON_UPLOAD_TEX0 ) {
+ radeon_emit_tex0( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_TEX0;
+ }
+
+ if ( dirty & RADEON_UPLOAD_TEX1 ) {
+ radeon_emit_tex1( dev_priv );
+ sarea_priv->dirty &= ~RADEON_UPLOAD_TEX1;
+ }
+
+ if ( dirty & RADEON_UPLOAD_TEX2 ) {
+#if 0
+ radeon_emit_tex2( dev_priv );
+#endif
+ sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2;
+ }
+
+ sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+ RADEON_UPLOAD_TEX1IMAGES |
+ RADEON_UPLOAD_TEX2IMAGES |
+ RADEON_REQUIRE_QUIESCENCE);
+}
+
+
+#if RADEON_PERFORMANCE_BOXES
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void radeon_clear_box( drm_radeon_private_t *dev_priv,
+ int x, int y, int w, int h,
+ int r, int g, int b )
+{
+ u32 pitch, offset;
+ u32 color;
+ RING_LOCALS;
+
+ switch ( dev_priv->color_fmt ) {
+ case RADEON_COLOR_FORMAT_RGB565:
+ color = (((r & 0xf8) << 8) |
+ ((g & 0xfc) << 3) |
+ ((b & 0xf8) >> 3));
+ break;
+ case RADEON_COLOR_FORMAT_ARGB8888:
+ default:
+ color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+ break;
+ }
+
+ offset = dev_priv->back_offset;
+ pitch = dev_priv->back_pitch >> 3;
+
+ BEGIN_RING( 6 );
+
+ OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P |
+ RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+ OUT_RING( (pitch << 22) | (offset >> 5) );
+ OUT_RING( color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+}
+
+static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
+{
+ if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
+ radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
+ } else {
+ atomic_set( &dev_priv->idle_count, 0 );
+ }
+}
+
+#endif
+
+
+/* ================================================================
+ * CP command dispatch functions
+ */
+
+static void radeon_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%s%s\n",
+ msg,
+ flags,
+ (flags & RADEON_UPLOAD_CONTEXT) ? "context, " : "",
+ (flags & RADEON_UPLOAD_VERTFMT) ? "vertfmt, " : "",
+ (flags & RADEON_UPLOAD_LINE) ? "line, " : "",
+ (flags & RADEON_UPLOAD_BUMPMAP) ? "bumpmap, " : "",
+ (flags & RADEON_UPLOAD_MASKS) ? "masks, " : "",
+ (flags & RADEON_UPLOAD_VIEWPORT) ? "viewport, " : "",
+ (flags & RADEON_UPLOAD_SETUP) ? "setup, " : "",
+ (flags & RADEON_UPLOAD_TCL) ? "tcl, " : "",
+ (flags & RADEON_UPLOAD_MISC) ? "misc, " : "",
+ (flags & RADEON_UPLOAD_TEX0) ? "tex0, " : "",
+ (flags & RADEON_UPLOAD_TEX1) ? "tex1, " : "",
+ (flags & RADEON_UPLOAD_TEX2) ? "tex2, " : "",
+ (flags & RADEON_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+ (flags & RADEON_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
+}
+
+static void radeon_cp_dispatch_clear( drm_device_t *dev,
+ drm_radeon_clear_t *clear,
+ drm_radeon_clear_rect_t *depth_boxes )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ unsigned int flags = clear->flags;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
+ unsigned int tmp = flags;
+
+ flags &= ~(RADEON_FRONT | RADEON_BACK);
+ if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
+ if ( tmp & RADEON_BACK ) flags |= RADEON_FRONT;
+ }
+
+ 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",
+ x, y, w, h, flags );
+
+ if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
+ BEGIN_RING( 4 );
+
+ /* Ensure the 3D stream is idle before doing a
+ * 2D fill to clear the front or back buffer.
+ */
+ RADEON_WAIT_UNTIL_3D_IDLE();
+
+ OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
+ OUT_RING( clear->color_mask );
+
+ ADVANCE_RING();
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+ RADEON_UPLOAD_MASKS);
+ }
+
+ if ( flags & RADEON_FRONT ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P |
+ RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+ OUT_RING( dev_priv->front_pitch_offset );
+ OUT_RING( clear->clear_color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+ }
+
+ if ( flags & RADEON_BACK ) {
+ BEGIN_RING( 6 );
+
+ OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+ OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_SOLID_COLOR |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_P |
+ RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+ OUT_RING( dev_priv->back_pitch_offset );
+ OUT_RING( clear->clear_color );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+
+ }
+
+ if ( flags & RADEON_DEPTH ) {
+ drm_radeon_depth_clear_t *depth_clear =
+ &dev_priv->depth_clear;
+
+ if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+ radeon_emit_state( dev_priv );
+ }
+
+ /* FIXME: Render a rectangle to clear the depth
+ * buffer. So much for those "fast Z clears"...
+ */
+ BEGIN_RING( 23 );
+
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+ OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
+ OUT_RING( 0x00000000 );
+ OUT_RING( depth_clear->rb3d_cntl );
+ OUT_RING( CP_PACKET0( RADEON_RB3D_ZSTENCILCNTL, 0 ) );
+ OUT_RING( depth_clear->rb3d_zstencilcntl );
+ OUT_RING( CP_PACKET0( RADEON_RB3D_PLANEMASK, 0 ) );
+ OUT_RING( 0x00000000 );
+ OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+ OUT_RING( depth_clear->se_cntl );
+
+ OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 10 ) );
+ OUT_RING( RADEON_VTX_Z_PRESENT );
+ OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
+ RADEON_PRIM_WALK_RING |
+ RADEON_MAOS_ENABLE |
+ RADEON_VTX_FMT_RADEON_MODE |
+ (3 << RADEON_NUM_VERTICES_SHIFT)) );
+
+ OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+ OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
+ OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+
+ OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+ OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+ OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+
+ OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
+ OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+ OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+
+ ADVANCE_RING();
+
+ /* Make sure we restore the 3D state next time.
+ */
+ dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+ RADEON_UPLOAD_SETUP |
+ RADEON_UPLOAD_MASKS);
+ }
+ }
+
+ /* Increment the clear counter. The client-side 3D driver must
+ * wait on this value before performing the clear ioctl. We
+ * need this because the card's so damned fast...
+ */
+ dev_priv->sarea_priv->last_clear++;
+
+ BEGIN_RING( 4 );
+
+ RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_swap( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int nbox = sarea_priv->nbox;
+ drm_clip_rect_t *pbox = sarea_priv->boxes;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+#if RADEON_PERFORMANCE_BOXES
+ /* Do some trivial performance monitoring...
+ */
+ radeon_cp_performance_boxes( dev_priv );
+#endif
+
+ /* Wait for the 3D stream to idle before dispatching the bitblt.
+ * This will prevent data corruption between the two streams.
+ */
+ BEGIN_RING( 2 );
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+
+ ADVANCE_RING();
+
+ 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",
+ x, y, w, h );
+
+ BEGIN_RING( 7 );
+
+ OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
+ OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+ RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ (dev_priv->color_fmt << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_MEMORY |
+ RADEON_GMC_CLR_CMP_CNTL_DIS |
+ RADEON_GMC_WR_MSK_DIS );
+
+ OUT_RING( dev_priv->back_pitch_offset );
+ OUT_RING( dev_priv->front_pitch_offset );
+
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (x << 16) | y );
+ OUT_RING( (w << 16) | h );
+
+ ADVANCE_RING();
+ }
+
+ /* Increment the frame counter. The client-side 3D driver must
+ * throttle the framerate by waiting for this value before
+ * performing the swapbuffer ioctl.
+ */
+ dev_priv->sarea_priv->last_frame++;
+
+ BEGIN_RING( 4 );
+
+ RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+ ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_flip( drm_device_t *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+ DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
+
+#if RADEON_PERFORMANCE_BOXES
+ /* Do some trivial performance monitoring...
+ */
+ radeon_cp_performance_boxes( dev_priv );
+#endif
+
+ BEGIN_RING( 6 );
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+ RADEON_WAIT_UNTIL_PAGE_FLIPPED();
+
+ OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 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;
+ }
+
+ ADVANCE_RING();
+
+ /* Increment the frame counter. The client-side 3D driver must
+ * throttle the framerate by waiting for this value before
+ * performing the swapbuffer ioctl.
+ */
+ dev_priv->sarea_priv->last_frame++;
+
+ BEGIN_RING( 2 );
+
+ RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
+
+ ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_vertex( 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;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int format = sarea_priv->vc_format;
+ int offset = dev_priv->agp_buffers_offset + buf->offset;
+ int size = buf->used;
+ int prim = buf_priv->prim;
+ int i = 0;
+ RING_LOCALS;
+ DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
+
+ if ( 0 )
+ radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
+
+ if ( buf->used ) {
+ buf_priv->dispatched = 1;
+
+ if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+ radeon_emit_state( dev_priv );
+ }
+
+ do {
+ /* Emit the next set of up to three cliprects */
+ if ( i < sarea_priv->nbox ) {
+ radeon_emit_clip_rect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+
+ /* Emit the vertex buffer rendering commands */
+ BEGIN_RING( 5 );
+
+ OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+ OUT_RING( offset );
+ OUT_RING( size );
+ OUT_RING( format );
+ OUT_RING( prim | RADEON_PRIM_WALK_LIST |
+ RADEON_COLOR_ORDER_RGBA |
+ RADEON_VTX_FMT_RADEON_MODE |
+ (size << RADEON_NUM_VERTICES_SHIFT) );
+
+ ADVANCE_RING();
+
+ i++;
+ } while ( i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+ BEGIN_RING( 2 );
+ RADEON_DISPATCH_AGE( buf_priv->age );
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ buf->used = 0;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+
+ sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
+ sarea_priv->nbox = 0;
+}
+
+
+static void radeon_cp_dispatch_indirect( drm_device_t *dev,
+ drm_buf_t *buf,
+ int start, int end )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+ RING_LOCALS;
+ DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
+ buf->idx, start, end );
+
+ if ( start != end ) {
+ int offset = (dev_priv->agp_buffers_offset
+ + buf->offset + start);
+ int dwords = (end - start + 3) / sizeof(u32);
+
+ /* Indirect buffer data must be an even number of
+ * dwords, so if we've been given an odd number we must
+ * pad the data with a Type-2 CP packet.
+ */
+ if ( dwords & 1 ) {
+ u32 *data = (u32 *)
+ ((char *)dev_priv->buffers->handle
+ + buf->offset + start);
+ data[dwords++] = RADEON_CP_PACKET2;
+ }
+
+ buf_priv->dispatched = 1;
+
+ /* Fire off the indirect buffer */
+ BEGIN_RING( 3 );
+
+ OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
+ OUT_RING( offset );
+ OUT_RING( dwords );
+
+ ADVANCE_RING();
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the indirect buffer age */
+ BEGIN_RING( 2 );
+ RADEON_DISPATCH_AGE( buf_priv->age );
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ buf->used = 0;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+}
+
+static void radeon_cp_dispatch_indices( drm_device_t *dev,
+ drm_buf_t *buf,
+ int start, int end,
+ int count )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ int format = sarea_priv->vc_format;
+ int offset = dev_priv->agp_buffers_offset;
+ int prim = buf_priv->prim;
+ u32 *data;
+ int dwords;
+ int i = 0;
+ RING_LOCALS;
+ DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
+
+ if ( 0 )
+ radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
+
+ if ( start != end ) {
+ buf_priv->dispatched = 1;
+
+ if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+ radeon_emit_state( dev_priv );
+ }
+
+ dwords = (end - start + 3) / sizeof(u32);
+
+ data = (u32 *)((char *)dev_priv->buffers->handle
+ + buf->offset + start);
+
+ data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
+
+ data[1] = offset;
+ data[2] = RADEON_MAX_VB_VERTS;
+ data[3] = format;
+ data[4] = (prim | RADEON_PRIM_WALK_IND |
+ RADEON_COLOR_ORDER_RGBA |
+ RADEON_VTX_FMT_RADEON_MODE |
+ (count << RADEON_NUM_VERTICES_SHIFT) );
+
+ if ( count & 0x1 ) {
+ data[dwords-1] &= 0x0000ffff;
+ }
+
+ do {
+ /* Emit the next set of up to three cliprects */
+ if ( i < sarea_priv->nbox ) {
+ radeon_emit_clip_rect( dev_priv,
+ &sarea_priv->boxes[i] );
+ }
+
+ radeon_cp_dispatch_indirect( dev, buf, start, end );
+
+ i++;
+ } while ( i < sarea_priv->nbox );
+ }
+
+ if ( buf_priv->discard ) {
+ buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+ /* Emit the vertex buffer age */
+ BEGIN_RING( 2 );
+ RADEON_DISPATCH_AGE( buf_priv->age );
+ ADVANCE_RING();
+
+ buf->pending = 1;
+ /* FIXME: Check dispatched field */
+ buf_priv->dispatched = 0;
+ }
+
+ dev_priv->sarea_priv->last_dispatch++;
+
+ sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
+ sarea_priv->nbox = 0;
+}
+
+#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
+
+static int radeon_cp_dispatch_texture( drm_device_t *dev,
+ drm_radeon_texture_t *tex,
+ drm_radeon_tex_image_t *image, int pid )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ u32 format;
+ u32 *buffer;
+ const u8 *data;
+ int size, dwords, tex_width, blit_width;
+ u32 y, height;
+ int ret = 0, i;
+ RING_LOCALS;
+
+ /* FIXME: Be smarter about this...
+ */
+ buf = radeon_freelist_get( dev );
+ if ( !buf ) DRM_OS_RETURN( EAGAIN );
+
+ DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+ tex->offset >> 10, tex->pitch, tex->format,
+ image->x, image->y, image->width, image->height );
+
+ buf_priv = buf->dev_private;
+
+ /* 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 ( tex->format ) {
+ case RADEON_TXFORMAT_ARGB8888:
+ case RADEON_TXFORMAT_RGBA8888:
+ format = RADEON_COLOR_FORMAT_ARGB8888;
+ tex_width = tex->width * 4;
+ blit_width = image->width * 4;
+ break;
+ case RADEON_TXFORMAT_AI88:
+ case RADEON_TXFORMAT_ARGB1555:
+ case RADEON_TXFORMAT_RGB565:
+ case RADEON_TXFORMAT_ARGB4444:
+ format = RADEON_COLOR_FORMAT_RGB565;
+ tex_width = tex->width * 2;
+ blit_width = image->width * 2;
+ break;
+ case RADEON_TXFORMAT_I8:
+ case RADEON_TXFORMAT_RGB332:
+ format = RADEON_COLOR_FORMAT_CI8;
+ tex_width = tex->width * 1;
+ blit_width = image->width * 1;
+ break;
+ default:
+ DRM_ERROR( "invalid texture format %d\n", tex->format );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ DRM_DEBUG( " tex=%dx%d blit=%d\n",
+ tex_width, tex->height, blit_width );
+
+ /* Flush the pixel cache. This ensures no pixel data gets mixed
+ * up with the texture data from the host data blit, otherwise
+ * part of the texture image may be corrupted.
+ */
+ BEGIN_RING( 4 );
+
+ RADEON_FLUSH_CACHE();
+ RADEON_WAIT_UNTIL_IDLE();
+
+ ADVANCE_RING();
+
+ /* Make a copy of the parameters in case we have to update them
+ * for a multi-pass texture blit.
+ */
+ y = image->y;
+ height = image->height;
+ data = image->data;
+
+ size = height * blit_width;
+
+ if ( size > RADEON_MAX_TEXTURE_SIZE ) {
+ /* Texture image is too large, do a multipass upload */
+ ret = EAGAIN;
+
+ /* Adjust the blit size to fit the indirect buffer */
+ height = RADEON_MAX_TEXTURE_SIZE / blit_width;
+ size = height * blit_width;
+
+ /* Update the input parameters for next time */
+ image->y += height;
+ image->height -= height;
+ image->data = (const char *)image->data + size;
+
+ if ( DRM_OS_COPYTOUSR( tex->image, image, sizeof(*image) ) ) {
+ DRM_ERROR( "EFAULT on tex->image\n" );
+ DRM_OS_RETURN( EFAULT );
+ }
+ } else if ( size < 4 && size > 0 ) {
+ size = 4;
+ }
+
+ dwords = size / 4;
+
+ /* Dispatch the indirect buffer.
+ */
+ buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+
+ buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
+ buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+ RADEON_GMC_BRUSH_NONE |
+ (format << 8) |
+ RADEON_GMC_SRC_DATATYPE_COLOR |
+ RADEON_ROP3_S |
+ RADEON_DP_SRC_SOURCE_HOST_DATA |
+ RADEON_GMC_CLR_CMP_CNTL_DIS |
+ RADEON_GMC_WR_MSK_DIS);
+
+ buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
+ buffer[3] = 0xffffffff;
+ buffer[4] = 0xffffffff;
+ buffer[5] = (y << 16) | image->x;
+ buffer[6] = (height << 16) | image->width;
+ buffer[7] = dwords;
+
+ buffer += 8;
+
+ if ( tex_width >= 32 ) {
+ /* Texture image width is larger than the minimum, so we
+ * can upload it directly.
+ */
+ if ( DRM_OS_COPYFROMUSR( buffer, data, dwords * sizeof(u32) ) ) {
+ DRM_ERROR( "EFAULT on data, %d dwords\n", dwords );
+ DRM_OS_RETURN( EFAULT );
+ }
+ } else {
+ /* Texture image width is less than the minimum, so we
+ * need to pad out each image scanline to the minimum
+ * width.
+ */
+ for ( i = 0 ; i < tex->height ; i++ ) {
+ if ( DRM_OS_COPYFROMUSR( buffer, data, tex_width ) ) {
+ DRM_ERROR( "EFAULT on pad, %d bytes\n",
+ tex_width );
+ DRM_OS_RETURN( EFAULT );
+ }
+ buffer += 8;
+ data += tex_width;
+ }
+ }
+
+ buf->pid = pid;
+ buf->used = (dwords + 8) * sizeof(u32);
+ buf_priv->discard = 1;
+
+ radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
+
+ /* Flush the pixel cache after the blit completes. This ensures
+ * the texture data is written out to memory before rendering
+ * continues.
+ */
+ BEGIN_RING( 4 );
+
+ RADEON_FLUSH_CACHE();
+ RADEON_WAIT_UNTIL_2D_IDLE();
+
+ ADVANCE_RING();
+
+ DRM_OS_RETURN( ret );
+}
+
+static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ int i;
+ RING_LOCALS;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ BEGIN_RING( 35 );
+
+ OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
+ OUT_RING( 0x00000000 );
+
+ OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
+ for ( i = 0 ; i < 32 ; i++ ) {
+ OUT_RING( stipple[i] );
+ }
+
+ ADVANCE_RING();
+}
+
+
+/* ================================================================
+ * IOCTL functions
+ */
+
+int radeon_cp_clear( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ drm_radeon_clear_t clear;
+ drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( clear, (drm_radeon_clear_t *) data,
+ sizeof(clear) );
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+ if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+ if ( DRM_OS_COPYFROMUSR( &depth_boxes, clear.depth_boxes,
+ sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
+ DRM_OS_RETURN( EFAULT );
+
+ radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
+
+ return 0;
+}
+
+int radeon_cp_swap( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+ if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
+ sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+ if ( !dev_priv->page_flipping ) {
+ radeon_cp_dispatch_swap( dev );
+ dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
+ RADEON_UPLOAD_MASKS);
+ } else {
+ radeon_cp_dispatch_flip( dev );
+ }
+
+ return 0;
+}
+
+int radeon_cp_vertex( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_radeon_vertex_t vertex;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ DRM_OS_KRNFROMUSR( vertex, (drm_radeon_vertex_t *) data,
+ sizeof(vertex) );
+
+ DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n",
+ __FUNCTION__, DRM_OS_CURRENTPID,
+ vertex.idx, vertex.count, vertex.discard );
+
+ if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ vertex.idx, dma->buf_count - 1 );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( vertex.prim < 0 ||
+ vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+ DRM_ERROR( "buffer prim %d\n", vertex.prim );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+ buf = dma->buflist[vertex.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != DRM_OS_CURRENTPID ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ buf->used = vertex.count;
+ buf_priv->prim = vertex.prim;
+ buf_priv->discard = vertex.discard;
+
+ radeon_cp_dispatch_vertex( dev, buf );
+
+ return 0;
+}
+
+int radeon_cp_indices( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_radeon_indices_t elts;
+ int count;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ DRM_OS_KRNFROMUSR( elts, (drm_radeon_indices_t *) data,
+ sizeof(elts) );
+
+ DRM_DEBUG( "%s: pid=%d index=%d start=%d end=%d discard=%d\n",
+ __FUNCTION__, DRM_OS_CURRENTPID,
+ elts.idx, elts.start, elts.end, elts.discard );
+
+ if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ elts.idx, dma->buf_count - 1 );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( elts.prim < 0 ||
+ elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+ DRM_ERROR( "buffer prim %d\n", elts.prim );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+ buf = dma->buflist[elts.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != DRM_OS_CURRENTPID ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", elts.idx );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ count = (elts.end - elts.start) / sizeof(u16);
+ elts.start -= RADEON_INDEX_PRIM_OFFSET;
+
+ if ( elts.start & 0x7 ) {
+ DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( elts.start < buf->used ) {
+ DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ buf->used = elts.end;
+ buf_priv->prim = elts.prim;
+ buf_priv->discard = elts.discard;
+
+ radeon_cp_dispatch_indices( dev, buf, elts.start, elts.end, count );
+
+ return 0;
+}
+
+int radeon_cp_texture( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_texture_t tex;
+ drm_radeon_tex_image_t image;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( tex, (drm_radeon_texture_t *) data, sizeof(tex) );
+
+ if ( tex.image == NULL ) {
+ DRM_ERROR( "null texture image!\n" );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ if ( DRM_OS_COPYFROMUSR( &image,
+ (drm_radeon_tex_image_t *)tex.image,
+ sizeof(image) ) )
+ DRM_OS_RETURN( EFAULT );
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+ return radeon_cp_dispatch_texture( dev, &tex, &image, DRM_OS_CURRENTPID );
+}
+
+int radeon_cp_stipple( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_radeon_stipple_t stipple;
+ u32 mask[32];
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ DRM_OS_KRNFROMUSR( stipple, (drm_radeon_stipple_t *) data,
+ sizeof(stipple) );
+
+ if ( DRM_OS_COPYFROMUSR( &mask, stipple.mask, 32 * sizeof(u32) ) )
+ DRM_OS_RETURN( EFAULT );
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+ radeon_cp_dispatch_stipple( dev, mask );
+
+ return 0;
+}
+
+int radeon_cp_indirect( DRM_OS_IOCTL )
+{
+ DRM_OS_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_device_dma_t *dma = dev->dma;
+ drm_buf_t *buf;
+ drm_radeon_buf_priv_t *buf_priv;
+ drm_radeon_indirect_t indirect;
+ RING_LOCALS;
+
+ LOCK_TEST_WITH_RETURN( dev );
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ DRM_OS_KRNFROMUSR( indirect, (drm_radeon_indirect_t *) data,
+ sizeof(indirect) );
+
+ DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
+ indirect.idx, indirect.start,
+ indirect.end, indirect.discard );
+
+ if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
+ DRM_ERROR( "buffer index %d (of %d max)\n",
+ indirect.idx, dma->buf_count - 1 );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ buf = dma->buflist[indirect.idx];
+ buf_priv = buf->dev_private;
+
+ if ( buf->pid != DRM_OS_CURRENTPID ) {
+ DRM_ERROR( "process %d using buffer owned by %d\n",
+ DRM_OS_CURRENTPID, buf->pid );
+ DRM_OS_RETURN( EINVAL );
+ }
+ if ( buf->pending ) {
+ DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ if ( indirect.start < buf->used ) {
+ DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
+ indirect.start, buf->used );
+ DRM_OS_RETURN( EINVAL );
+ }
+
+ RING_SPACE_TEST_WITH_RETURN( dev_priv );
+ VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+ buf->used = indirect.end;
+ buf_priv->discard = indirect.discard;
+
+ /* Wait for the 3D stream to idle before the indirect buffer
+ * containing 2D acceleration commands is processed.
+ */
+ BEGIN_RING( 2 );
+
+ RADEON_WAIT_UNTIL_3D_IDLE();
+
+ ADVANCE_RING();
+
+ /* Dispatch the indirect buffer full of commands from the
+ * X server. This is insecure and is thus only available to
+ * privileged clients.
+ */
+ radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+
+ return 0;
+}
diff --git a/sys/dev/drm/sis_drm.h b/sys/dev/drm/sis_drm.h
new file mode 100644
index 0000000..dad43bc
--- /dev/null
+++ b/sys/dev/drm/sis_drm.h
@@ -0,0 +1,33 @@
+/*
+ * $FreeBSD$
+ */
+
+#ifndef _sis_drm_public_h_
+#define _sis_drm_public_h_
+
+typedef struct {
+ int context;
+ unsigned int offset;
+ unsigned int size;
+ unsigned int free;
+} drm_sis_mem_t;
+
+typedef struct {
+ unsigned int offset, size;
+} drm_sis_agp_t;
+
+typedef struct {
+ unsigned int left, right;
+} drm_sis_flip_t;
+
+#if defined(__KERNEL__) || defined(_KERNEL)
+
+int sis_fb_alloc(DRM_OS_IOCTL);
+int sis_fb_free(DRM_OS_IOCTL);
+int sisp_agp_init(DRM_OS_IOCTL);
+int sisp_agp_alloc(DRM_OS_IOCTL);
+int sisp_agp_free(DRM_OS_IOCTL);
+
+#endif
+
+#endif
diff --git a/sys/dev/drm/tdfx.h b/sys/dev/drm/tdfx.h
new file mode 100644
index 0000000..39333ea
--- /dev/null
+++ b/sys/dev/drm/tdfx.h
@@ -0,0 +1,44 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __TDFX_H__
+#define __TDFX_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) tdfx_##x
+
+/* General customization:
+ */
+#define __HAVE_MTRR 1
+#define __HAVE_CTX_BITMAP 1
+
+#endif
diff --git a/sys/dev/drm/tdfx_drv.c b/sys/dev/drm/tdfx_drv.c
new file mode 100644
index 0000000..ecf7db2
--- /dev/null
+++ b/sys/dev/drm/tdfx_drv.c
@@ -0,0 +1,152 @@
+/* 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>
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __linux__
+#include <linux/config.h>
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <pci/pcivar.h>
+#include <opt_drm_linux.h>
+#endif /* __FreeBSD__ */
+
+#include "dev/drm/tdfx.h"
+#include "dev/drm/drmP.h"
+
+#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
+
+#ifndef PCI_VENDOR_ID_3DFX
+#define PCI_VENDOR_ID_3DFX 0x121A
+#endif
+#ifndef PCI_DEVICE_ID_3DFX_VOODOO5
+#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
+#endif
+#ifndef PCI_DEVICE_ID_3DFX_VOODOO4
+#define PCI_DEVICE_ID_3DFX_VOODOO4 0x0007
+#endif
+#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_3000 /* Voodoo3 3000 */
+#define PCI_DEVICE_ID_3DFX_VOODOO3_3000 0x0005
+#endif
+#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_2000 /* Voodoo3 3000 */
+#define PCI_DEVICE_ID_3DFX_VOODOO3_2000 0x0004
+#endif
+#ifndef PCI_DEVICE_ID_3DFX_BANSHEE
+#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003
+#endif
+
+#ifdef __FreeBSD__
+/* List acquired from xc/xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h
+ * Please report to eanholt@gladstone.uoregon.edu if your chip isn't
+ * represented in the list or if the information is incorrect.
+ */
+drm_chipinfo_t DRM(devicelist)[] = {
+ {0x121a, 0x0003, 1, "3dfx Voodoo Banshee"},
+ {0x121a, 0x0004, 1, "3dfx Voodoo3 2000"},
+ {0x121a, 0x0005, 1, "3dfx Voodoo3 3000"},
+ {0x121a, 0x0007, 1, "3dfx Voodoo4"},
+ {0x121a, 0x0009, 1, "3dfx Voodoo5"},
+ {0, 0, 0, NULL}
+};
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+/* For now, we'll only support multihead on Linux */
+/* Uncomment this, and fixup drm_count_cards */
+static drm_pci_list_t DRM(idlist)[] = {
+ { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE },
+ { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_2000 },
+ { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_3000 },
+ { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO4 },
+ { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5 },
+ { 0, 0 }
+};
+
+#define DRIVER_CARD_LIST DRM(idlist)
+#endif /* __linux__ */
+
+#include "dev/drm/drm_auth.h"
+#include "dev/drm/drm_bufs.h"
+#include "dev/drm/drm_context.h"
+#include "dev/drm/drm_dma.h"
+#include "dev/drm/drm_drawable.h"
+#include "dev/drm/drm_drv.h"
+
+#ifdef __linux__
+#ifndef MODULE
+/* DRM(options) is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO). It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+
+/* JH- We have to hand expand the string ourselves because of the cpp. If
+ * anyone can think of a way that we can fit into the __setup macro without
+ * changing it, then please send the solution my way.
+ */
+static int __init tdfx_options( char *str )
+{
+ DRM(parse_options)( str );
+ return 1;
+}
+
+__setup( DRIVER_NAME "=", tdfx_options );
+#endif
+#endif /* __linux__ */
+
+#include "dev/drm/drm_fops.h"
+#include "dev/drm/drm_init.h"
+#include "dev/drm/drm_ioctl.h"
+#include "dev/drm/drm_lock.h"
+#include "dev/drm/drm_memory.h"
+#ifdef __linux__
+#include "dev/drm/drm_proc.h"
+#endif /* __linux__ */
+#include "dev/drm/drm_vm.h"
+#ifdef __linux__
+#include "dev/drm/drm_stub.h"
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include "dev/drm/drm_sysctl.h"
+
+DRIVER_MODULE(tdfx, pci, tdfx_driver, tdfx_devclass, 0, 0);
+#endif /* __FreeBSD__ */
OpenPOWER on IntegriCloud