diff options
author | anholt <anholt@FreeBSD.org> | 2003-03-09 02:08:30 +0000 |
---|---|---|
committer | anholt <anholt@FreeBSD.org> | 2003-03-09 02:08:30 +0000 |
commit | ccdf4ef2d9288d035e56820efb0e79db6acf5ba8 (patch) | |
tree | ef9d3b03548e9f28bd5c265be746871660c0c16a | |
parent | 0b60094f80a8137660b368df0b80fb0179b92d04 (diff) | |
download | FreeBSD-src-ccdf4ef2d9288d035e56820efb0e79db6acf5ba8.zip FreeBSD-src-ccdf4ef2d9288d035e56820efb0e79db6acf5ba8.tar.gz |
Update the DRM to latest from DRI CVS. This is approximately the version
included in XFree86 4.3, but includes some fixes. Notable changes include
Radeon 8500-9100 support, PCI Radeon/Rage 128 support, transform & lighting
support for Radeons, and vblank syncing support for r128, radeon, and mga.
The gamma driver was removed due to lack of any users.
58 files changed, 6128 insertions, 5842 deletions
diff --git a/sys/conf/files b/sys/conf/files index 52b7eae..94a68c8 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -355,17 +355,19 @@ dev/digi/Xr.c optional digi_Xr dev/dpt/dpt_eisa.c optional dpt eisa dev/dpt/dpt_pci.c optional dpt pci dev/dpt/dpt_scsi.c optional dpt -dev/drm/gamma_dma.c optional gammadrm -dev/drm/gamma_drv.c optional gammadrm dev/drm/mga_dma.c optional mgadrm dev/drm/mga_drv.c optional mgadrm +dev/drm/mga_irq.c optional mgadrm dev/drm/mga_state.c optional mgadrm dev/drm/mga_warp.c optional mgadrm dev/drm/r128_cce.c optional r128drm dev/drm/r128_drv.c optional r128drm +dev/drm/r128_irq.c optional r128drm dev/drm/r128_state.c optional r128drm dev/drm/radeon_cp.c optional radeondrm dev/drm/radeon_drv.c optional radeondrm +dev/drm/radeon_irq.c optional radeondrm +dev/drm/radeon_mem.c optional radeondrm dev/drm/radeon_state.c optional radeondrm dev/drm/tdfx_drv.c optional tdfxdrm dev/ed/if_ed.c optional ed diff --git a/sys/dev/drm/ati_pcigart.h b/sys/dev/drm/ati_pcigart.h new file mode 100644 index 0000000..0eafcc0 --- /dev/null +++ b/sys/dev/drm/ati_pcigart.h @@ -0,0 +1,113 @@ +/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*- + * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com + * + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes <gareth@valinux.com> + * + * $FreeBSD$ + */ + +#include "dev/drm/drmP.h" + +#if PAGE_SIZE == 8192 +# define ATI_PCIGART_TABLE_ORDER 2 +# define ATI_PCIGART_TABLE_PAGES (1 << 2) +#elif PAGE_SIZE == 4096 +# define ATI_PCIGART_TABLE_ORDER 3 +# define ATI_PCIGART_TABLE_PAGES (1 << 3) +#elif +# error - PAGE_SIZE not 8K or 4K +#endif + +# define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */ +# define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */ + +int DRM(ati_pcigart_init)( drm_device_t *dev, + unsigned long *addr, + dma_addr_t *bus_addr) +{ + drm_sg_mem_t *entry = dev->sg; + unsigned long address = 0; + unsigned long pages; + u32 *pci_gart=0, page_base, bus_address = 0; + int i, j, ret = 0; + + if ( !entry ) { + DRM_ERROR( "no scatter/gather memory!\n" ); + goto done; + } + + address = (long)contigmalloc((1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE, + DRM(M_DRM), M_WAITOK, 0ul, 0xfffffffful, PAGE_SIZE, 0); + if ( !address ) { + DRM_ERROR( "cannot allocate PCI GART page!\n" ); + goto done; + } + + /* XXX: we need to busdma this */ + bus_address = vtophys( address ); + + pci_gart = (u32 *)address; + + pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) + ? entry->pages : ATI_MAX_PCIGART_PAGES; + + bzero( pci_gart, ATI_MAX_PCIGART_PAGES * sizeof(u32) ); + + for ( i = 0 ; i < pages ; i++ ) { + entry->busaddr[i] = vtophys( entry->handle + (i*PAGE_SIZE) ); + page_base = (u32) entry->busaddr[i]; + + for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { + *pci_gart++ = cpu_to_le32( page_base ); + page_base += ATI_PCIGART_PAGE_SIZE; + } + } + + ret = 1; + +done: + *addr = address; + *bus_addr = bus_address; + return ret; +} + +int DRM(ati_pcigart_cleanup)( drm_device_t *dev, + unsigned long addr, + dma_addr_t bus_addr) +{ + drm_sg_mem_t *entry = dev->sg; + + /* we need to support large memory configurations */ + if ( !entry ) { + DRM_ERROR( "no scatter/gather memory!\n" ); + return 0; + } + +#if __FreeBSD_version > 500000 + contigfree( (void *)addr, (1 << ATI_PCIGART_TABLE_ORDER) * PAGE_SIZE, DRM(M_DRM)); /* Not available on 4.x */ +#endif + return 1; +} diff --git a/sys/dev/drm/drm.h b/sys/dev/drm/drm.h index 5f33bb5..4a51aba 100644 --- a/sys/dev/drm/drm.h +++ b/sys/dev/drm/drm.h @@ -36,15 +36,31 @@ #ifndef _DRM_H_ #define _DRM_H_ -#ifdef __linux__ +#if defined(__linux__) #include <linux/config.h> #include <asm/ioctl.h> /* For _IO* macros */ -#define DRM_IOCTL_NR(n) _IOC_NR(n) -#endif /* __linux__ */ -#ifdef __FreeBSD__ +#define DRM_IOCTL_NR(n) _IOC_NR(n) +#define DRM_IOC_VOID _IOC_NONE +#define DRM_IOC_READ _IOC_READ +#define DRM_IOC_WRITE _IOC_WRITE +#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) +#elif defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__FreeBSD__) && defined(XFree86Server) +/* Prevent name collision when including sys/ioccom.h */ +#undef ioctl #include <sys/ioccom.h> -#define DRM_IOCTL_NR(n) ((n) & 0xff) -#endif /* __FreeBSD__ */ +#define ioctl(a,b,c) xf86ioctl(a,b,c) +#else +#include <sys/ioccom.h> +#endif /* __FreeBSD__ && xf86ioctl */ +#define DRM_IOCTL_NR(n) ((n) & 0xff) +#define DRM_IOC_VOID IOC_VOID +#define DRM_IOC_READ IOC_OUT +#define DRM_IOC_WRITE IOC_IN +#define DRM_IOC_READWRITE IOC_INOUT +#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) +#endif #define XFREE86_VERSION(major,minor,patch,snap) \ ((major << 16) | (minor << 8) | patch) @@ -70,7 +86,7 @@ #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_RAM_PERCENT 10 /* 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 */ @@ -86,6 +102,10 @@ typedef unsigned int drm_magic_t; /* Warning: If you change this structure, make sure you change * XF86DRIClipRectRec in the server as well */ +/* KW: Actually it's illegal to change either for + * backwards-compatibility reasons. + */ + typedef struct drm_clip_rect { unsigned short x1; unsigned short y1; @@ -326,6 +346,32 @@ typedef struct drm_irq_busid { int funcnum; } drm_irq_busid_t; +typedef enum { + _DRM_VBLANK_ABSOLUTE = 0x0, /* Wait for specific vblank sequence number */ + _DRM_VBLANK_RELATIVE = 0x1, /* Wait for given number of vblanks */ + _DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ +} drm_vblank_seq_type_t; + +#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL + +struct drm_wait_vblank_request { + drm_vblank_seq_type_t type; + unsigned int sequence; + unsigned long signal; +}; + +struct drm_wait_vblank_reply { + drm_vblank_seq_type_t type; + unsigned int sequence; + long tval_sec; + long tval_usec; +}; + +typedef union drm_wait_vblank { + struct drm_wait_vblank_request request; + struct drm_wait_vblank_reply reply; +} drm_wait_vblank_t; + typedef struct drm_agp_mode { unsigned long mode; } drm_agp_mode_t; @@ -365,10 +411,9 @@ typedef struct drm_scatter_gather { #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_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) +#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) +#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) #define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t) #define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t) @@ -421,4 +466,10 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t) #define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t) +#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) + +/* Device specfic ioctls should only be in their respective headers + * The device specific ioctl range is 0x40 to 0x79. */ +#define DRM_COMMAND_BASE 0x40 + #endif diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h index d84c8bd..7e6849b 100644 --- a/sys/dev/drm/drmP.h +++ b/sys/dev/drm/drmP.h @@ -27,7 +27,6 @@ * Authors: * Rickard E. (Rik) Faith <faith@valinux.com> * Gareth Hughes <gareth@valinux.com> - * * $FreeBSD$ */ @@ -70,13 +69,12 @@ 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__ */ +#elif defined __NetBSD__ +#include "dev/drm/drm_os_netbsd.h" +#endif #include "dev/drm/drm.h" @@ -116,14 +114,23 @@ typedef struct drm_file drm_file_t; #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 ) + (map)->handle = DRM(ioremap)( dev, map ) + +#define DRM_IOREMAP_NOCACHE(map) \ + (map)->handle = DRM(ioremap_nocache)( dev, map ) #define DRM_IOREMAPFREE(map) \ do { \ if ( (map)->handle && (map)->size ) \ - DRM(ioremapfree)( (map)->handle, (map)->size ); \ + DRM(ioremapfree)( map ); \ } while (0) /* Internal types and structures */ @@ -139,7 +146,6 @@ typedef struct drm_file drm_file_t; (_map) = (_dev)->context_sareas[_ctx]; \ } while(0) -typedef int drm_ioctl_t( DRM_OS_IOCTL ); typedef struct drm_pci_list { u16 vendor; @@ -147,7 +153,7 @@ typedef struct drm_pci_list { } drm_pci_list_t; typedef struct drm_ioctl_desc { - drm_ioctl_t *func; + d_ioctl_t *func; int auth_needed; int root_only; } drm_ioctl_desc_t; @@ -238,8 +244,8 @@ typedef struct drm_waitlist { 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_SPINTYPE read_lock; + DRM_SPINTYPE write_lock; } drm_waitlist_t; typedef struct drm_freelist { @@ -251,7 +257,7 @@ typedef struct drm_freelist { 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_SPINTYPE lock; } drm_freelist_t; typedef struct drm_buf_entry { @@ -270,21 +276,6 @@ typedef struct drm_hw_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; @@ -297,7 +288,6 @@ struct drm_file { unsigned long ioctl_count; struct drm_device *devXX; }; -#endif /* __FreeBSD__ */ typedef struct drm_queue { atomic_t use_count; /* Outstanding uses (+1) */ @@ -362,13 +352,7 @@ typedef struct drm_device_dma { #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; @@ -376,13 +360,8 @@ typedef struct drm_agp_mem { } 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; @@ -399,10 +378,7 @@ 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 { @@ -410,51 +386,53 @@ typedef struct drm_sigdata { 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 struct drm_local_map { + unsigned long offset; /* Physical address (0 for SAREA)*/ + unsigned long size; /* Physical size (bytes) */ + drm_map_type_t type; /* Type of memory mapped */ + 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 */ + bus_space_tag_t iot; + bus_space_handle_t ioh; +} drm_local_map_t; + 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_local_map_t *map; } drm_map_list_entry_t; -#endif /* __FreeBSD__ */ + +TAILQ_HEAD(drm_vbl_sig_list, drm_vbl_sig); +typedef struct drm_vbl_sig { + TAILQ_ENTRY(drm_vbl_sig) link; + unsigned int sequence; + int signo; + int pid; +} drm_vbl_sig_t; struct drm_device { +#ifdef __NetBSD__ + struct device device; /* NetBSD's softc is an extension of struct device */ +#endif 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 */ +#endif 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__ */ -#ifdef __linux__ - struct proc_dir_entry *root; /* Root for this device's entries */ -#endif /* __linux__ */ /* Locks */ - DRM_OS_SPINTYPE count_lock; /* For inuse, open_count, buf_use */ -#ifdef __linux__ - struct semaphore struct_sem; /* For others */ -#endif /* __linux__ */ -#ifdef __FreeBSD__ + DRM_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 */ @@ -468,20 +446,14 @@ struct drm_device { 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; + drm_local_map_t **context_sareas; int max_context; drm_vma_entry_t *vmalist; /* List of vmas (for debugging) */ @@ -496,31 +468,33 @@ struct drm_device { /* Context support */ int irq; /* Interrupt used by board */ + int irqrid; /* Interrupt used by board */ #ifdef __FreeBSD__ struct resource *irqr; /* Resource for interrupt used by board */ +#elif defined(__NetBSD__) + struct pci_attach_args pa; + pci_intr_handle_t ih; +#endif 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__ + atomic_t context_flag; /* Context swapping flag */ + atomic_t interrupt_flag; /* Interruption handler flag */ + atomic_t dma_flag; /* DMA dispatch flag */ 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__ */ +#if __HAVE_VBL_IRQ + wait_queue_head_t vbl_queue; /* vbl wait channel */ + atomic_t vbl_received; +#if 0 /* vbl signals are untested, ntested */ + struct drm_vbl_sig_list vbl_sig_list; + DRM_SPINTYPE vbl_lock; +#endif +#endif cycles_t ctx_start; cycles_t lck_start; #if __HAVE_DMA_HISTOGRAM @@ -533,68 +507,54 @@ struct drm_device { 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 */ +#elif defined(__NetBSD__) + pid_t buf_pgid; +#endif 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; + atomic_t *ctx_bitmap; void *dev_private; drm_sigdata_t sigdata; /* For block_all_signals */ sigset_t sigmask; }; -/* ================================================================ - * Internal function definitions - */ - 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(ioctl)( DRM_OS_IOCTL ); -extern int DRM(lock)( DRM_OS_IOCTL ); -extern int DRM(unlock)( DRM_OS_IOCTL ); -extern int DRM(write_string)(drm_device_t *dev, const char *s); +extern int DRM(version)( DRM_IOCTL_ARGS ); +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(mem_uninit)(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); +extern void *DRM(ioremap)(drm_device_t *dev, drm_local_map_t *map); +extern void *DRM(ioremap_nocache)(drm_device_t *dev, drm_local_map_t *map); +extern void DRM(ioremapfree)(drm_local_map_t *map); #if __REALLY_HAVE_AGP extern agp_memory *DRM(alloc_agp)(int pages, u32 type); @@ -603,23 +563,6 @@ extern int DRM(bind_agp)(agp_memory *handle, unsigned int start); extern int DRM(unbind_agp)(agp_memory *handle); #endif - /* Misc. IOCTL support (drm_ioctl.h) */ -extern int DRM(irq_busid)( DRM_OS_IOCTL ); -extern int DRM(getunique)( DRM_OS_IOCTL ); -extern int DRM(setunique)( DRM_OS_IOCTL ); -extern int DRM(getmap)( DRM_OS_IOCTL ); -extern int DRM(getclient)( DRM_OS_IOCTL ); -extern int DRM(getstats)( DRM_OS_IOCTL ); - - /* Context IOCTL support (drm_context.h) */ -extern int DRM(resctx)( DRM_OS_IOCTL ); -extern int DRM(addctx)( DRM_OS_IOCTL ); -extern int DRM(modctx)( DRM_OS_IOCTL ); -extern int DRM(getctx)( DRM_OS_IOCTL ); -extern int DRM(switchctx)( DRM_OS_IOCTL ); -extern int DRM(newctx)( DRM_OS_IOCTL ); -extern int DRM(rmctx)( DRM_OS_IOCTL ); - 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); @@ -630,24 +573,7 @@ extern void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle ); extern int DRM(ctxbitmap_next)( drm_device_t *dev ); #endif -extern int DRM(setsareactx)( DRM_OS_IOCTL ); -extern int DRM(getsareactx)( DRM_OS_IOCTL ); - - /* Drawable IOCTL support (drm_drawable.h) */ -extern int DRM(adddraw)( DRM_OS_IOCTL ); -extern int DRM(rmdraw)( DRM_OS_IOCTL ); - - /* Authentication IOCTL support (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); -extern int DRM(getmagic)( DRM_OS_IOCTL ); -extern int DRM(authmagic)( DRM_OS_IOCTL ); - /* Locking IOCTL support (drm_lock.h) */ -extern int DRM(block)( DRM_OS_IOCTL ); -extern int DRM(unblock)( DRM_OS_IOCTL ); -extern int DRM(finish)( DRM_OS_IOCTL ); extern int DRM(lock_take)(__volatile__ unsigned int *lock, unsigned int context); extern int DRM(lock_transfer)(drm_device_t *dev, @@ -664,17 +590,8 @@ extern int DRM(notifier)(void *priv); /* Buffer management support (drm_bufs.h) */ extern int DRM(order)( unsigned long size ); -extern int DRM(addmap)( DRM_OS_IOCTL ); -extern int DRM(rmmap)( DRM_OS_IOCTL ); #if __HAVE_DMA -extern int DRM(addbufs)( DRM_OS_IOCTL ); -extern int DRM(infobufs)( DRM_OS_IOCTL ); -extern int DRM(markbufs)( DRM_OS_IOCTL ); -extern int DRM(freebufs)( DRM_OS_IOCTL ); -extern int DRM(mapbufs)( DRM_OS_IOCTL ); -extern int DRM(control)( DRM_OS_IOCTL ); - /* DMA support (drm_dma.h) */ extern int DRM(dma_setup)(drm_device_t *dev); extern void DRM(dma_takedown)(drm_device_t *dev); @@ -692,9 +609,12 @@ extern int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma); #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 ); +extern void DRM(dma_service)( DRM_IRQ_ARGS ); +extern void DRM(driver_irq_preinstall)( drm_device_t *dev ); +extern void DRM(driver_irq_postinstall)( drm_device_t *dev ); +extern void DRM(driver_irq_uninstall)( drm_device_t *dev ); #if __HAVE_DMA_IRQ_BH -extern void DRM(dma_immediate_bh)( DRM_OS_TASKQUEUE_ARGS ); +extern void DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS ); #endif #endif #if DRM_DMA_HISTOGRAM @@ -717,17 +637,13 @@ extern int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, extern drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block); #endif #endif /* __HAVE_DMA */ +#if __HAVE_VBL_IRQ +extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq); +extern void DRM(vbl_send_signals)( drm_device_t *dev ); +#endif #if __REALLY_HAVE_AGP /* AGP/GART support (drm_agpsupport.h) */ -extern int DRM(agp_acquire)( DRM_OS_IOCTL ); -extern int DRM(agp_release)( DRM_OS_IOCTL ); -extern int DRM(agp_enable)( DRM_OS_IOCTL ); -extern int DRM(agp_info)( DRM_OS_IOCTL ); -extern int DRM(agp_alloc)( DRM_OS_IOCTL ); -extern int DRM(agp_free)( DRM_OS_IOCTL ); -extern int DRM(agp_unbind)( DRM_OS_IOCTL ); -extern int DRM(agp_bind)( DRM_OS_IOCTL ); extern drm_agp_head_t *DRM(agp_init)(void); extern void DRM(agp_uninit)(void); extern void DRM(agp_do_release)(void); @@ -740,8 +656,6 @@ extern int DRM(agp_unbind_memory)(agp_memory *handle); #if __HAVE_SG /* Scatter Gather Support (drm_scatter.h) */ extern void DRM(sg_cleanup)(drm_sg_mem_t *entry); -extern int DRM(sg_alloc)( DRM_OS_IOCTL ); -extern int DRM(sg_free)( DRM_OS_IOCTL ); #endif #if __REALLY_HAVE_SG @@ -755,4 +669,4 @@ extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev, #endif #endif /* __KERNEL__ */ -#endif +#endif /* _DRM_P_H_ */ diff --git a/sys/dev/drm/drm_agpsupport.h b/sys/dev/drm/drm_agpsupport.h index a625c28..df9ce0a 100644 --- a/sys/dev/drm/drm_agpsupport.h +++ b/sys/dev/drm/drm_agpsupport.h @@ -27,27 +27,19 @@ * 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) +int DRM(agp_info)(DRM_IOCTL_ARGS) { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; struct agp_info *kern; drm_agp_info_t info; - if (!dev->agp || !dev->agp->acquired) return EINVAL; + if (!dev->agp || !dev->agp->acquired) + return EINVAL; kern = &dev->agp->info; agp_get_info(dev->agp->agpdev, kern); @@ -65,21 +57,23 @@ int DRM(agp_info)(DRM_OS_IOCTL) return 0; } -int DRM(agp_acquire)(DRM_OS_IOCTL) +int DRM(agp_acquire)(DRM_IOCTL_ARGS) { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; int retcode; - if (!dev->agp || dev->agp->acquired) return EINVAL; + if (!dev->agp || dev->agp->acquired) + return EINVAL; retcode = agp_acquire(dev->agp->agpdev); - if (retcode) return retcode; + if (retcode) + return retcode; dev->agp->acquired = 1; return 0; } -int DRM(agp_release)(DRM_OS_IOCTL) +int DRM(agp_release)(DRM_IOCTL_ARGS) { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; if (!dev->agp || !dev->agp->acquired) return EINVAL; @@ -93,17 +87,18 @@ void DRM(agp_do_release)(void) { device_t agpdev; - agpdev = agp_find_device(); + agpdev = DRM_AGP_FIND_DEVICE(); if (agpdev) agp_release(agpdev); } -int DRM(agp_enable)(DRM_OS_IOCTL) +int DRM(agp_enable)(DRM_IOCTL_ARGS) { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; drm_agp_mode_t mode; - if (!dev->agp || !dev->agp->acquired) return EINVAL; + if (!dev->agp || !dev->agp->acquired) + return EINVAL; mode = *(drm_agp_mode_t *) data; @@ -114,9 +109,9 @@ int DRM(agp_enable)(DRM_OS_IOCTL) return 0; } -int DRM(agp_alloc)(DRM_OS_IOCTL) +int DRM(agp_alloc)(DRM_IOCTL_ARGS) { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; drm_agp_buffer_t request; drm_agp_mem_t *entry; void *handle; @@ -124,7 +119,8 @@ int DRM(agp_alloc)(DRM_OS_IOCTL) u_int32_t type; struct agp_memory_info info; - if (!dev->agp || !dev->agp->acquired) return EINVAL; + if (!dev->agp || !dev->agp->acquired) + return EINVAL; request = *(drm_agp_buffer_t *) data; @@ -146,7 +142,8 @@ int DRM(agp_alloc)(DRM_OS_IOCTL) entry->pages = pages; entry->prev = NULL; entry->next = dev->agp->memory; - if (dev->agp->memory) dev->agp->memory->prev = entry; + if (dev->agp->memory) + dev->agp->memory->prev = entry; dev->agp->memory = entry; agp_memory_info(dev->agp->agpdev, entry->handle, &info); @@ -169,14 +166,15 @@ static drm_agp_mem_t * DRM(agp_lookup_entry)(drm_device_t *dev, void *handle) return NULL; } -int DRM(agp_unbind)(DRM_OS_IOCTL) +int DRM(agp_unbind)(DRM_IOCTL_ARGS) { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; drm_agp_binding_t request; drm_agp_mem_t *entry; int retcode; - if (!dev->agp || !dev->agp->acquired) return EINVAL; + 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; @@ -191,9 +189,9 @@ int DRM(agp_unbind)(DRM_OS_IOCTL) return retcode; } -int DRM(agp_bind)(DRM_OS_IOCTL) +int DRM(agp_bind)(DRM_IOCTL_ARGS) { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; drm_agp_binding_t request; drm_agp_mem_t *entry; int retcode; @@ -213,21 +211,26 @@ int DRM(agp_bind)(DRM_OS_IOCTL) return 0; } -int DRM(agp_free)(DRM_OS_IOCTL) +int DRM(agp_free)(DRM_IOCTL_ARGS) { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; drm_agp_buffer_t request; drm_agp_mem_t *entry; - if (!dev->agp || !dev->agp->acquired) return EINVAL; + 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->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; + 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; @@ -239,7 +242,7 @@ drm_agp_head_t *DRM(agp_init)(void) drm_agp_head_t *head = NULL; int agp_available = 1; - agpdev = agp_find_device(); + agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev) agp_available = 0; @@ -271,9 +274,9 @@ drm_agp_head_t *DRM(agp_init)(void) default: } #endif - DRM_INFO("AGP at 0x%08x %dMB\n", - head->info.ai_aperture_base, - head->info.ai_aperture_size >> 20); + DRM_INFO("AGP at 0x%08lx %dMB\n", + (long)head->info.ai_aperture_base, + (int)(head->info.ai_aperture_size >> 20)); } return head; } @@ -288,7 +291,7 @@ agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type) { device_t agpdev; - agpdev = agp_find_device(); + agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev) return NULL; @@ -299,7 +302,7 @@ int DRM(agp_free_memory)(agp_memory *handle) { device_t agpdev; - agpdev = agp_find_device(); + agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev || !handle) return 0; @@ -311,7 +314,7 @@ int DRM(agp_bind_memory)(agp_memory *handle, off_t start) { device_t agpdev; - agpdev = agp_find_device(); + agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev || !handle) return EINVAL; @@ -322,7 +325,7 @@ int DRM(agp_unbind_memory)(agp_memory *handle) { device_t agpdev; - agpdev = agp_find_device(); + agpdev = DRM_AGP_FIND_DEVICE(); if (!agpdev || !handle) return EINVAL; diff --git a/sys/dev/drm/drm_auth.h b/sys/dev/drm/drm_auth.h index 4eb62ab..1e08b05 100644 --- a/sys/dev/drm/drm_auth.h +++ b/sys/dev/drm/drm_auth.h @@ -27,11 +27,9 @@ * 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) @@ -45,14 +43,14 @@ static drm_file_t *DRM(find_file)(drm_device_t *dev, drm_magic_t magic) drm_magic_entry_t *pt; int hash = DRM(hash_magic)(magic); - DRM_OS_LOCK; + DRM_LOCK; for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { if (pt->magic == magic) { retval = pt->priv; break; } } - DRM_OS_UNLOCK; + DRM_UNLOCK; return retval; } @@ -65,12 +63,13 @@ int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) hash = DRM(hash_magic)(magic); entry = (drm_magic_entry_t*) DRM(alloc)(sizeof(*entry), DRM_MEM_MAGIC); - if (!entry) return DRM_OS_ERR(ENOMEM); + if (!entry) return DRM_ERR(ENOMEM); + memset(entry, 0, sizeof(*entry)); entry->magic = magic; entry->priv = priv; entry->next = NULL; - DRM_OS_LOCK; + DRM_LOCK; if (dev->magiclist[hash].tail) { dev->magiclist[hash].tail->next = entry; dev->magiclist[hash].tail = entry; @@ -78,7 +77,7 @@ int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) dev->magiclist[hash].head = entry; dev->magiclist[hash].tail = entry; } - DRM_OS_UNLOCK; + DRM_UNLOCK; return 0; } @@ -92,7 +91,7 @@ int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic) DRM_DEBUG("%d\n", magic); hash = DRM(hash_magic)(magic); - DRM_OS_LOCK; + DRM_LOCK; for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { if (pt->magic == magic) { if (dev->magiclist[hash].head == pt) { @@ -104,49 +103,34 @@ int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic) if (prev) { prev->next = pt->next; } - DRM_OS_UNLOCK; -#ifdef __FreeBSD__ - DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC); -#endif /* __FreeBSD__ */ + DRM_UNLOCK; return 0; } } - DRM_OS_UNLOCK; + DRM_UNLOCK; DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } -int DRM(getmagic)(DRM_OS_IOCTL) +int DRM(getmagic)(DRM_IOCTL_ARGS) { 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__ */ + DRM_DEVICE; + DRM_PRIV; /* 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); + int old = sequence; + + auth.magic = old+1; + + if (!atomic_cmpset_int(&sequence, old, auth.magic)) + continue; } while (DRM(find_file)(dev, auth.magic)); priv->magic = auth.magic; DRM(add_magic)(dev, priv, auth.magic); @@ -154,18 +138,18 @@ int DRM(getmagic)(DRM_OS_IOCTL) DRM_DEBUG("%u\n", auth.magic); - DRM_OS_KRNTOUSR((drm_auth_t *)data, auth, sizeof(auth)); + DRM_COPY_TO_USER_IOCTL((drm_auth_t *)data, auth, sizeof(auth)); return 0; } -int DRM(authmagic)(DRM_OS_IOCTL) +int DRM(authmagic)(DRM_IOCTL_ARGS) { drm_auth_t auth; drm_file_t *file; - DRM_OS_DEVICE; + DRM_DEVICE; - DRM_OS_KRNFROMUSR(auth, (drm_auth_t *)data, sizeof(auth)); + DRM_COPY_FROM_USER_IOCTL(auth, (drm_auth_t *)data, sizeof(auth)); DRM_DEBUG("%u\n", auth.magic); if ((file = DRM(find_file)(dev, auth.magic))) { @@ -173,5 +157,5 @@ int DRM(authmagic)(DRM_OS_IOCTL) DRM(remove_magic)(dev, auth.magic); return 0; } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } diff --git a/sys/dev/drm/drm_bufs.h b/sys/dev/drm/drm_bufs.h index 1524e9d..92855a7 100644 --- a/sys/dev/drm/drm_bufs.h +++ b/sys/dev/drm/drm_bufs.h @@ -27,23 +27,9 @@ * 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 @@ -65,16 +51,6 @@ #endif #endif -#if __REALLY_HAVE_AGP -int DRM(addbufs_agp)( DRM_OS_IOCTL ); -#endif -#if __HAVE_PCI_DMA -int DRM(addbufs_pci)( DRM_OS_IOCTL ); -#endif -#if __REALLY_HAVE_SG -int DRM(addbufs_sg)( DRM_OS_IOCTL ); -#endif - /* * Compute order. Can be made faster. */ @@ -91,100 +67,85 @@ int DRM(order)( unsigned long size ) return order; } -int DRM(addmap)( DRM_OS_IOCTL ) +int DRM(addmap)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; - drm_map_t *map; -#ifdef __linux__ - drm_map_list_t *list; -#endif /* __linux__ */ -#ifdef __FreeBSD__ + DRM_DEVICE; + drm_map_t request; + drm_local_map_t *map; 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__ */ - return DRM_OS_ERR(EACCES); /* Require read/write */ + return DRM_ERR(EACCES); /* Require read/write */ - map = (drm_map_t *) DRM(alloc)( sizeof(*map), DRM_MEM_MAPS ); - if ( !map ) - return DRM_OS_ERR(ENOMEM); + DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(drm_map_t) ); -#ifdef __linux__ - if ( copy_from_user( map, (drm_map_t *)data, sizeof(*map) ) ) { - DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); - return DRM_OS_ERR(EFAULT); - } -#endif /* __linux__ */ -#ifdef __FreeBSD__ - *map = *(drm_map_t *)data; -#endif /* __FreeBSD__ */ + map = (drm_local_map_t *) DRM(alloc)( sizeof(*map), DRM_MEM_MAPS ); + if ( !map ) + return DRM_ERR(ENOMEM); + map->offset = request.offset; + map->size = request.size; + map->type = request.type; + map->flags = request.flags; + map->mtrr = -1; + map->handle = 0; + /* 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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } - map->mtrr = -1; - map->handle = 0; 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__ */ - ) { + if ( map->offset + map->size < map->offset ) { DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); - } +#ifdef __FreeBSD__ + int retcode = 0, act; + struct mem_range_desc mrdesc; + mrdesc.mr_base = map->offset; + mrdesc.mr_len = map->size; + mrdesc.mr_flags = MDF_WRITECOMBINE; + act = MEMRANGE_SET_UPDATE; + bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME)); + retcode = mem_range_attr_set(&mrdesc, &act); + map->mtrr=1; +#elif defined __NetBSD__ + struct mtrr mtrrmap; + int one = 1; + mtrrmap.base = map->offset; + mtrrmap.len = map->size; + mtrrmap.type = MTRR_TYPE_WC; + mtrrmap.flags = MTRR_VALID; + map->mtrr = mtrr_set( &mtrrmap, &one, p, MTRR_GETSET_KERNEL ); #endif - map->handle = DRM(ioremap)( map->offset, map->size ); + } +#endif /* __REALLY_HAVE_MTRR */ + DRM_IOREMAP(map); 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__ */ + map->handle = (void *)DRM(alloc)(map->size, DRM_MEM_SAREA); 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 ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } map->offset = (unsigned long)map->handle; if ( map->flags & _DRM_CONTAINS_LOCK ) { @@ -193,9 +154,6 @@ int DRM(addmap)( DRM_OS_IOCTL ) 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; @@ -203,52 +161,41 @@ int DRM(addmap)( DRM_OS_IOCTL ) case _DRM_SCATTER_GATHER: if (!dev->sg) { DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } map->offset = map->offset + dev->sg->handle; break; default: DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } list = DRM(alloc)(sizeof(*list), DRM_MEM_MAPS); if(!list) { DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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__ + DRM_LOCK; TAILQ_INSERT_TAIL(dev->maplist, list, link); -#endif /* __FreeBSD__ */ - DRM_OS_UNLOCK; + DRM_UNLOCK; -#ifdef __linux__ - if ( copy_to_user( (drm_map_t *)data, map, sizeof(*map) ) ) - return DRM_OS_ERR(EFAULT); -#endif /* __linux__ */ -#ifdef __FreeBSD__ - *(drm_map_t *)data = *map; -#endif /* __FreeBSD__ */ + request.offset = map->offset; + request.size = map->size; + request.type = map->type; + request.flags = map->flags; + request.mtrr = map->mtrr; + request.handle = map->handle; - if ( map->type != _DRM_SHM ) { -#ifdef __linux__ - if ( copy_to_user( &((drm_map_t *)data)->handle, - &map->offset, - sizeof(map->offset) ) ) - return DRM_OS_ERR(EFAULT); -#endif /* __linux__ */ -#ifdef __FreeBSD__ - ((drm_map_t *)data)->handle = (void *)map->offset; -#endif /* __FreeBSD__ */ + if ( request.type != _DRM_SHM ) { + request.handle = (void *)request.offset; } + + DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, request, sizeof(drm_map_t) ); + return 0; } @@ -257,45 +204,17 @@ int DRM(addmap)( DRM_OS_IOCTL ) * isn't in use. */ -int DRM(rmmap)( DRM_OS_IOCTL ) +int DRM(rmmap)( DRM_IOCTL_ARGS ) { - 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_DEVICE; drm_map_list_entry_t *list; -#endif /* __FreeBSD__ */ - drm_map_t *map; + drm_local_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; + DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(request) ); - 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; - return DRM_OS_ERR(EINVAL); - } - map = r_list->map; - list_del(list); -#endif /* __linux__ */ -#ifdef __FreeBSD__ + DRM_LOCK; TAILQ_FOREACH(list, dev->maplist, link) { map = list->map; if(map->handle == request.handle && @@ -306,18 +225,12 @@ int DRM(rmmap)( DRM_OS_IOCTL ) * find anything. */ if(list == NULL) { - DRM_OS_UNLOCK; - return DRM_OS_ERR(EINVAL); + DRM_UNLOCK; + return DRM_ERR(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) { @@ -326,21 +239,32 @@ int DRM(rmmap)( DRM_OS_IOCTL ) #if __REALLY_HAVE_MTRR if (map->mtrr >= 0) { int retcode; - retcode = mtrr_del(map->mtrr, - map->offset, - map->size); +#ifdef __FreeBSD__ + int act; + struct mem_range_desc mrdesc; + mrdesc.mr_base = map->offset; + mrdesc.mr_len = map->size; + mrdesc.mr_flags = MDF_WRITECOMBINE; + act = MEMRANGE_SET_REMOVE; + bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME)); + retcode = mem_range_attr_set(&mrdesc, &act); +#elif defined __NetBSD__ + struct mtrr mtrrmap; + int one = 1; + mtrrmap.base = map->offset; + mtrrmap.len = map->size; + mtrrmap.type = 0; + mtrrmap.flags = 0; + mtrrmap.owner = p->p_pid; + retcode = mtrr_set( &mtrrmap, &one, p, MTRR_GETSET_KERNEL); DRM_DEBUG("mtrr_del = %d\n", retcode); +#endif } #endif - DRM(ioremapfree)(map->handle, map->size); + DRM(ioremapfree)( map ); 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__ */ + DRM(free)( map->handle, map->size, DRM_MEM_SAREA ); break; case _DRM_AGP: case _DRM_SCATTER_GATHER: @@ -348,7 +272,7 @@ int DRM(rmmap)( DRM_OS_IOCTL ) } DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); } - DRM_OS_UNLOCK; + DRM_UNLOCK; return 0; } @@ -361,8 +285,8 @@ static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry) if (entry->seg_count) { for (i = 0; i < entry->seg_count; i++) { - DRM(free_pages)(entry->seglist[i], - entry->page_order, + DRM(free)((void *)entry->seglist[i], + entry->buf_size, DRM_MEM_DMA); } DRM(free)(entry->seglist, @@ -395,9 +319,9 @@ static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry) } #if __REALLY_HAVE_AGP -int DRM(addbufs_agp)( DRM_OS_IOCTL ) +int DRM(addbufs_agp)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_desc_t request; drm_buf_entry_t *entry; @@ -414,21 +338,16 @@ int DRM(addbufs_agp)( DRM_OS_IOCTL ) int i; drm_buf_t **temp_buflist; - if ( !dma ) return DRM_OS_ERR(EINVAL); + if ( !dma ) return DRM_ERR(EINVAL); - DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) ); + DRM_COPY_FROM_USER_IOCTL( 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; @@ -444,38 +363,38 @@ int DRM(addbufs_agp)( DRM_OS_IOCTL ) DRM_DEBUG( "total: %d\n", total ); if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); if ( dev->queue_count ) - return DRM_OS_ERR(EBUSY); /* Not while in use */ + return DRM_ERR(EBUSY); /* Not while in use */ - DRM_OS_SPINLOCK( &dev->count_lock ); + DRM_SPINLOCK( &dev->count_lock ); if ( dev->buf_use ) { - DRM_OS_SPINUNLOCK( &dev->count_lock ); - return DRM_OS_ERR(EBUSY); + DRM_SPINUNLOCK( &dev->count_lock ); + return DRM_ERR(EBUSY); } atomic_inc( &dev->buf_alloc ); - DRM_OS_SPINUNLOCK( &dev->count_lock ); + DRM_SPINUNLOCK( &dev->count_lock ); - DRM_OS_LOCK; + DRM_LOCK; entry = &dma->bufs[order]; if ( entry->buf_count ) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); /* May only call once for each order */ + return DRM_ERR(ENOMEM); /* May only call once for each order */ } if (count < 0 || count > 4096) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), DRM_MEM_BUFS ); if ( !entry->buflist ) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } memset( entry->buflist, 0, count * sizeof(*entry->buflist) ); @@ -497,12 +416,7 @@ int DRM(addbufs_agp)( DRM_OS_IOCTL ) 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); @@ -537,9 +451,9 @@ int DRM(addbufs_agp)( DRM_OS_IOCTL ) if(!temp_buflist) { /* Free the entry because it isn't valid */ DRM(cleanup_buf_error)(entry); - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } dma->buflist = temp_buflist; @@ -559,12 +473,12 @@ int DRM(addbufs_agp)( DRM_OS_IOCTL ) DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); } #endif - DRM_OS_UNLOCK; + DRM_UNLOCK; request.count = entry->buf_count; request.size = size; - DRM_OS_KRNTOUSR( (drm_buf_desc_t *)data, request, sizeof(request) ); + DRM_COPY_TO_USER_IOCTL( (drm_buf_desc_t *)data, request, sizeof(request) ); dma->flags = _DRM_DMA_USE_AGP; @@ -574,9 +488,9 @@ int DRM(addbufs_agp)( DRM_OS_IOCTL ) #endif /* __REALLY_HAVE_AGP */ #if __HAVE_PCI_DMA -int DRM(addbufs_pci)( DRM_OS_IOCTL ) +int DRM(addbufs_pci)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_desc_t request; int count; @@ -595,9 +509,9 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) unsigned long *temp_pagelist; drm_buf_t **temp_buflist; - if ( !dma ) return DRM_OS_ERR(EINVAL); + if ( !dma ) return DRM_ERR(EINVAL); - DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) ); + DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) ); count = request.count; order = DRM(order)( request.size ); @@ -608,48 +522,43 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) order, dev->queue_count ); if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); if ( dev->queue_count ) - return DRM_OS_ERR(EBUSY); /* Not while in use */ + return DRM_ERR(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 ); + DRM_SPINLOCK( &dev->count_lock ); if ( dev->buf_use ) { - DRM_OS_SPINUNLOCK( &dev->count_lock ); - return DRM_OS_ERR(EBUSY); + DRM_SPINUNLOCK( &dev->count_lock ); + return DRM_ERR(EBUSY); } atomic_inc( &dev->buf_alloc ); - DRM_OS_SPINUNLOCK( &dev->count_lock ); + DRM_SPINUNLOCK( &dev->count_lock ); - DRM_OS_LOCK; + DRM_LOCK; entry = &dma->bufs[order]; if ( entry->buf_count ) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); /* May only call once for each order */ + return DRM_ERR(ENOMEM); /* May only call once for each order */ } if (count < 0 || count > 4096) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), DRM_MEM_BUFS ); if ( !entry->buflist ) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } memset( entry->buflist, 0, count * sizeof(*entry->buflist) ); @@ -659,9 +568,9 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) DRM(free)( entry->buflist, count * sizeof(*entry->buflist), DRM_MEM_BUFS ); - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } memset( entry->seglist, 0, count * sizeof(*entry->seglist) ); @@ -677,9 +586,9 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) DRM(free)( entry->seglist, count * sizeof(*entry->seglist), DRM_MEM_SEGS ); - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } dma->pagelist = temp_pagelist; @@ -692,7 +601,7 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) page_count = 0; while ( entry->buf_count < count ) { - page = DRM(alloc_pages)( page_order, DRM_MEM_DMA ); + page = (unsigned long)DRM(alloc)( size, DRM_MEM_DMA ); if ( !page ) break; entry->seglist[entry->seg_count++] = page; for ( i = 0 ; i < (1 << page_order) ; i++ ) { @@ -715,12 +624,7 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) 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; @@ -742,9 +646,9 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) if(!temp_buflist) { /* Free the entry because it isn't valid */ DRM(cleanup_buf_error)(entry); - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } dma->buflist = temp_buflist; @@ -763,12 +667,12 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); } #endif - DRM_OS_UNLOCK; + DRM_UNLOCK; request.count = entry->buf_count; request.size = size; - DRM_OS_KRNTOUSR( (drm_buf_desc_t *)data, request, sizeof(request) ); + DRM_COPY_TO_USER_IOCTL( (drm_buf_desc_t *)data, request, sizeof(request) ); atomic_dec( &dev->buf_alloc ); return 0; @@ -777,9 +681,9 @@ int DRM(addbufs_pci)( DRM_OS_IOCTL ) #endif /* __HAVE_PCI_DMA */ #if __REALLY_HAVE_SG -int DRM(addbufs_sg)( DRM_OS_IOCTL ) +int DRM(addbufs_sg)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_desc_t request; drm_buf_entry_t *entry; @@ -796,21 +700,16 @@ int DRM(addbufs_sg)( DRM_OS_IOCTL ) int i; drm_buf_t **temp_buflist; - if ( !dma ) return DRM_OS_ERR(EINVAL); + if ( !dma ) return DRM_ERR(EINVAL); - DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) ); + DRM_COPY_FROM_USER_IOCTL( 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; @@ -826,37 +725,37 @@ int DRM(addbufs_sg)( DRM_OS_IOCTL ) DRM_DEBUG( "total: %d\n", total ); if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) - return DRM_OS_ERR(EINVAL); - if ( dev->queue_count ) return DRM_OS_ERR(EBUSY); /* Not while in use */ + return DRM_ERR(EINVAL); + if ( dev->queue_count ) return DRM_ERR(EBUSY); /* Not while in use */ - DRM_OS_SPINLOCK( &dev->count_lock ); + DRM_SPINLOCK( &dev->count_lock ); if ( dev->buf_use ) { - DRM_OS_SPINUNLOCK( &dev->count_lock ); - return DRM_OS_ERR(EBUSY); + DRM_SPINUNLOCK( &dev->count_lock ); + return DRM_ERR(EBUSY); } atomic_inc( &dev->buf_alloc ); - DRM_OS_SPINUNLOCK( &dev->count_lock ); + DRM_SPINUNLOCK( &dev->count_lock ); - DRM_OS_LOCK; + DRM_LOCK; entry = &dma->bufs[order]; if ( entry->buf_count ) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); /* May only call once for each order */ + return DRM_ERR(ENOMEM); /* May only call once for each order */ } if (count < 0 || count > 4096) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), DRM_MEM_BUFS ); if ( !entry->buflist ) { - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } memset( entry->buflist, 0, count * sizeof(*entry->buflist) ); @@ -878,12 +777,7 @@ int DRM(addbufs_sg)( DRM_OS_IOCTL ) 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); @@ -893,9 +787,9 @@ int DRM(addbufs_sg)( DRM_OS_IOCTL ) /* Set count correctly so we free the proper amount. */ entry->buf_count = count; DRM(cleanup_buf_error)(entry); - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } memset( buf->dev_private, 0, buf->dev_priv_size ); @@ -924,9 +818,9 @@ int DRM(addbufs_sg)( DRM_OS_IOCTL ) if(!temp_buflist) { /* Free the entry because it isn't valid */ DRM(cleanup_buf_error)(entry); - DRM_OS_UNLOCK; + DRM_UNLOCK; atomic_dec( &dev->buf_alloc ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } dma->buflist = temp_buflist; @@ -946,12 +840,12 @@ int DRM(addbufs_sg)( DRM_OS_IOCTL ) DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); } #endif - DRM_OS_UNLOCK; + DRM_UNLOCK; request.count = entry->buf_count; request.size = size; - DRM_OS_KRNTOUSR( (drm_buf_desc_t *)data, request, sizeof(request) ); + DRM_COPY_TO_USER_IOCTL( (drm_buf_desc_t *)data, request, sizeof(request) ); dma->flags = _DRM_DMA_USE_SG; @@ -960,48 +854,48 @@ int DRM(addbufs_sg)( DRM_OS_IOCTL ) } #endif /* __REALLY_HAVE_SG */ -int DRM(addbufs)( DRM_OS_IOCTL ) +int DRM(addbufs)( DRM_IOCTL_ARGS ) { drm_buf_desc_t request; - DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) ); + DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) ); #if __REALLY_HAVE_AGP if ( request.flags & _DRM_AGP_BUFFER ) - return DRM(addbufs_agp)( IOCTL_ARGS_PASS ); + return DRM(addbufs_agp)( kdev, cmd, data, flags, p ); else #endif #if __REALLY_HAVE_SG if ( request.flags & _DRM_SG_BUFFER ) - return DRM(addbufs_sg)( IOCTL_ARGS_PASS ); + return DRM(addbufs_sg)( kdev, cmd, data, flags, p ); else #endif #if __HAVE_PCI_DMA - return DRM(addbufs_pci)( IOCTL_ARGS_PASS ); + return DRM(addbufs_pci)( kdev, cmd, data, flags, p ); #else - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); #endif } -int DRM(infobufs)( DRM_OS_IOCTL ) +int DRM(infobufs)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_info_t request; int i; int count; - if ( !dma ) return DRM_OS_ERR(EINVAL); + if ( !dma ) return DRM_ERR(EINVAL); - DRM_OS_SPINLOCK( &dev->count_lock ); + DRM_SPINLOCK( &dev->count_lock ); if ( atomic_read( &dev->buf_alloc ) ) { - DRM_OS_SPINUNLOCK( &dev->count_lock ); - return DRM_OS_ERR(EBUSY); + DRM_SPINUNLOCK( &dev->count_lock ); + return DRM_ERR(EBUSY); } ++dev->buf_use; /* Can't allocate more after this call */ - DRM_OS_SPINUNLOCK( &dev->count_lock ); + DRM_SPINUNLOCK( &dev->count_lock ); - DRM_OS_KRNFROMUSR( request, (drm_buf_info_t *)data, sizeof(request) ); + DRM_COPY_FROM_USER_IOCTL( 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; @@ -1015,19 +909,19 @@ int DRM(infobufs)( DRM_OS_IOCTL ) 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, + if ( DRM_COPY_TO_USER( &to->count, &from->buf_count, sizeof(from->buf_count) ) || - DRM_OS_COPYTOUSR( &to->size, + DRM_COPY_TO_USER( &to->size, &from->buf_size, sizeof(from->buf_size) ) || - DRM_OS_COPYTOUSR( &to->low_mark, + DRM_COPY_TO_USER( &to->low_mark, &list->low_mark, sizeof(list->low_mark) ) || - DRM_OS_COPYTOUSR( &to->high_mark, + DRM_COPY_TO_USER( &to->high_mark, &list->high_mark, sizeof(list->high_mark) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); DRM_DEBUG( "%d %d %d %d %d\n", i, @@ -1041,34 +935,34 @@ int DRM(infobufs)( DRM_OS_IOCTL ) } request.count = count; - DRM_OS_KRNTOUSR( (drm_buf_info_t *)data, request, sizeof(request) ); + DRM_COPY_TO_USER_IOCTL( (drm_buf_info_t *)data, request, sizeof(request) ); return 0; } -int DRM(markbufs)( DRM_OS_IOCTL ) +int DRM(markbufs)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_desc_t request; int order; drm_buf_entry_t *entry; - if ( !dma ) return DRM_OS_ERR(EINVAL); + if ( !dma ) return DRM_ERR(EINVAL); - DRM_OS_KRNFROMUSR( request, (drm_buf_desc_t *)data, sizeof(request) ); + DRM_COPY_FROM_USER_IOCTL( 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 ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); entry = &dma->bufs[order]; if ( request.low_mark < 0 || request.low_mark > entry->buf_count ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); if ( request.high_mark < 0 || request.high_mark > entry->buf_count ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); entry->freelist.low_mark = request.low_mark; entry->freelist.high_mark = request.high_mark; @@ -1076,35 +970,35 @@ int DRM(markbufs)( DRM_OS_IOCTL ) return 0; } -int DRM(freebufs)( DRM_OS_IOCTL ) +int DRM(freebufs)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_device_dma_t *dma = dev->dma; drm_buf_free_t request; int i; int idx; drm_buf_t *buf; - if ( !dma ) return DRM_OS_ERR(EINVAL); + if ( !dma ) return DRM_ERR(EINVAL); - DRM_OS_KRNFROMUSR( request, (drm_buf_free_t *)data, sizeof(request) ); + DRM_COPY_FROM_USER_IOCTL( 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, + if ( DRM_COPY_FROM_USER( &idx, &request.list[i], sizeof(idx) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); if ( idx < 0 || idx >= dma->buf_count ) { DRM_ERROR( "Index %d (of %d max)\n", idx, dma->buf_count - 1 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } buf = dma->buflist[idx]; - if ( buf->pid != DRM_OS_CURRENTPID ) { + if ( buf->pid != DRM_CURRENTPID ) { DRM_ERROR( "Process %d freeing buffer owned by %d\n", - DRM_OS_CURRENTPID, buf->pid ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); } DRM(free_buffer)( dev, buf ); } @@ -1112,65 +1006,55 @@ int DRM(freebufs)( DRM_OS_IOCTL ) return 0; } -int DRM(mapbufs)( DRM_OS_IOCTL ) +int DRM(mapbufs)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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; +#ifdef __FreeBSD__ #if __FreeBSD_version >= 500000 struct vmspace *vms = p->td_proc->p_vmspace; #else struct vmspace *vms = p->p_vmspace; #endif #endif /* __FreeBSD__ */ +#ifdef __NetBSD__ + struct vnode *vn; + struct vmspace *vms = p->p_vmspace; +#endif /* __NetBSD__ */ + drm_buf_map_t request; int i; - if ( !dma ) return DRM_OS_ERR(EINVAL); + if ( !dma ) return DRM_ERR(EINVAL); - DRM_OS_SPINLOCK( &dev->count_lock ); + DRM_SPINLOCK( &dev->count_lock ); if ( atomic_read( &dev->buf_alloc ) ) { - DRM_OS_SPINUNLOCK( &dev->count_lock ); - return DRM_OS_ERR(EBUSY); + DRM_SPINUNLOCK( &dev->count_lock ); + return DRM_ERR(EBUSY); } dev->buf_use++; /* Can't allocate more after this call */ - DRM_OS_SPINUNLOCK( &dev->count_lock ); + DRM_SPINUNLOCK( &dev->count_lock ); - DRM_OS_KRNFROMUSR( request, (drm_buf_map_t *)data, sizeof(request) ); + DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_map_t *)data, sizeof(request) ); + +#ifdef __NetBSD__ + if(!vfinddev(kdev, VCHR, &vn)) + return 0; /* FIXME: Shouldn't this be EINVAL or something? */ +#endif /* __NetBSD__ */ 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 ); + drm_local_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev ); if ( !map ) { - retcode = DRM_OS_ERR(EINVAL); + retcode = EINVAL; goto done; } -#ifdef __linux__ -#if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); -#else - down_write( ¤t->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( ¤t->mm->mmap_sem ); -#else - up_write( ¤t->mm->mmap_sem ); -#endif -#endif /* __linux__ */ #ifdef __FreeBSD__ virtual = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ); retcode = vm_mmap(&vms->vm_map, @@ -1180,24 +1064,17 @@ int DRM(mapbufs)( DRM_OS_IOCTL ) MAP_SHARED, SLIST_FIRST(&kdev->si_hlist), (unsigned long)map->offset ); -#endif /* __FreeBSD__ */ +#elif defined(__NetBSD__) + virtual = round_page((vaddr_t)vms->vm_daddr + MAXDSIZ); + retcode = uvm_mmap(&vms->vm_map, + (vaddr_t *)&virtual, + round_page(map->size), + UVM_PROT_READ | UVM_PROT_WRITE, + UVM_PROT_ALL, MAP_SHARED, + &vn->v_uobj, map->offset, + p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); +#endif /* __NetBSD__ */ } else { -#ifdef __linux__ -#if LINUX_VERSION_CODE <= 0x020402 - down( ¤t->mm->mmap_sem ); -#else - down_write( ¤t->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( ¤t->mm->mmap_sem ); -#else - up_write( ¤t->mm->mmap_sem ); -#endif -#endif /* __linux__ */ #ifdef __FreeBSD__ virtual = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ); retcode = vm_mmap(&vms->vm_map, @@ -1207,45 +1084,45 @@ int DRM(mapbufs)( DRM_OS_IOCTL ) MAP_SHARED, SLIST_FIRST(&kdev->si_hlist), 0); -#endif /* __FreeBSD__ */ - } -#ifdef __linux__ - if ( virtual > -1024UL ) { - /* Real error */ - retcode = (signed long)virtual; - goto done; +#elif defined(__NetBSD__) + virtual = round_page((vaddr_t)vms->vm_daddr + MAXDSIZ); + retcode = uvm_mmap(&vms->vm_map, + (vaddr_t *)&virtual, + round_page(dma->byte_count), + UVM_PROT_READ | UVM_PROT_WRITE, + UVM_PROT_ALL, MAP_SHARED, + &vn->v_uobj, 0, + p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); +#endif /* __NetBSD__ */ } -#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, + if ( DRM_COPY_TO_USER( &request.list[i].idx, &dma->buflist[i]->idx, sizeof(request.list[0].idx) ) ) { - retcode = DRM_OS_ERR(EFAULT); + retcode = EFAULT; goto done; } - if ( DRM_OS_COPYTOUSR( &request.list[i].total, + if ( DRM_COPY_TO_USER( &request.list[i].total, &dma->buflist[i]->total, sizeof(request.list[0].total) ) ) { - retcode = DRM_OS_ERR(EFAULT); + retcode = EFAULT; goto done; } - if ( DRM_OS_COPYTOUSR( &request.list[i].used, + if ( DRM_COPY_TO_USER( &request.list[i].used, &zero, sizeof(zero) ) ) { - retcode = DRM_OS_ERR(EFAULT); + retcode = EFAULT; goto done; } address = virtual + dma->buflist[i]->offset; /* *** */ - if ( DRM_OS_COPYTOUSR( &request.list[i].address, + if ( DRM_COPY_TO_USER( &request.list[i].address, &address, sizeof(address) ) ) { - retcode = DRM_OS_ERR(EFAULT); + retcode = EFAULT; goto done; } } @@ -1255,9 +1132,9 @@ int DRM(mapbufs)( DRM_OS_IOCTL ) DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode ); - DRM_OS_KRNTOUSR( (drm_buf_map_t *)data, request, sizeof(request) ); + DRM_COPY_TO_USER_IOCTL( (drm_buf_map_t *)data, request, sizeof(request) ); - return retcode; + return DRM_ERR(retcode); } #endif /* __HAVE_DMA */ diff --git a/sys/dev/drm/drm_context.h b/sys/dev/drm/drm_context.h index ec70483..a46fecd 100644 --- a/sys/dev/drm/drm_context.h +++ b/sys/dev/drm/drm_context.h @@ -27,11 +27,9 @@ * 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 @@ -46,10 +44,10 @@ void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle ) if ( !dev->ctx_bitmap ) goto failed; if ( ctx_handle < DRM_MAX_CTXBITMAP ) { - DRM_OS_LOCK; + DRM_LOCK; clear_bit( ctx_handle, dev->ctx_bitmap ); dev->context_sareas[ctx_handle] = NULL; - DRM_OS_UNLOCK; + DRM_UNLOCK; return; } failed: @@ -64,7 +62,7 @@ int DRM(ctxbitmap_next)( drm_device_t *dev ) if(!dev->ctx_bitmap) return -1; - DRM_OS_LOCK; + DRM_LOCK; bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP ); if ( bit < DRM_MAX_CTXBITMAP ) { set_bit( bit, dev->ctx_bitmap ); @@ -72,7 +70,7 @@ int DRM(ctxbitmap_next)( drm_device_t *dev ) if((bit+1) > dev->max_context) { dev->max_context = (bit+1); if(dev->context_sareas) { - drm_map_t **ctx_sareas; + drm_local_map_t **ctx_sareas; ctx_sareas = DRM(realloc)(dev->context_sareas, (dev->max_context - 1) * @@ -82,7 +80,7 @@ int DRM(ctxbitmap_next)( drm_device_t *dev ) DRM_MEM_MAPS); if(!ctx_sareas) { clear_bit(bit, dev->ctx_bitmap); - DRM_OS_UNLOCK; + DRM_UNLOCK; return -1; } dev->context_sareas = ctx_sareas; @@ -95,16 +93,16 @@ int DRM(ctxbitmap_next)( drm_device_t *dev ) DRM_MEM_MAPS); if(!dev->context_sareas) { clear_bit(bit, dev->ctx_bitmap); - DRM_OS_UNLOCK; + DRM_UNLOCK; return -1; } dev->context_sareas[bit] = NULL; } } - DRM_OS_UNLOCK; + DRM_UNLOCK; return bit; } - DRM_OS_UNLOCK; + DRM_UNLOCK; return -1; } @@ -113,17 +111,17 @@ 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_LOCK; + dev->ctx_bitmap = (atomic_t *) DRM(alloc)( PAGE_SIZE, DRM_MEM_CTXBITMAP ); if ( dev->ctx_bitmap == NULL ) { - DRM_OS_UNLOCK; - return DRM_OS_ERR(ENOMEM); + DRM_UNLOCK; + return DRM_ERR(ENOMEM); } memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE ); dev->context_sareas = NULL; dev->max_context = -1; - DRM_OS_UNLOCK; + DRM_UNLOCK; for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) { temp = DRM(ctxbitmap_next)( dev ); @@ -135,96 +133,71 @@ int DRM(ctxbitmap_init)( drm_device_t *dev ) void DRM(ctxbitmap_cleanup)( drm_device_t *dev ) { - DRM_OS_LOCK; + DRM_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; + DRM_UNLOCK; } /* ================================================================ * Per Context SAREA Support */ -int DRM(getsareactx)( DRM_OS_IOCTL ) +int DRM(getsareactx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_priv_map_t request; - drm_map_t *map; + drm_local_map_t *map; - DRM_OS_KRNFROMUSR( request, (drm_ctx_priv_map_t *)data, + DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data, sizeof(request) ); - DRM_OS_LOCK; + DRM_LOCK; if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) { - DRM_OS_UNLOCK; - return DRM_OS_ERR(EINVAL); + DRM_UNLOCK; + return DRM_ERR(EINVAL); } map = dev->context_sareas[request.ctx_id]; - DRM_OS_UNLOCK; + DRM_UNLOCK; request.handle = map->handle; - DRM_OS_KRNTOUSR( (drm_ctx_priv_map_t *)data, request, sizeof(request) ); + DRM_COPY_TO_USER_IOCTL( (drm_ctx_priv_map_t *)data, request, sizeof(request) ); return 0; } -int DRM(setsareactx)( DRM_OS_IOCTL ) +int DRM(setsareactx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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_local_map_t *map = NULL; drm_map_list_entry_t *list; -#endif /* __FreeBSD__ */ - DRM_OS_KRNFROMUSR( request, (drm_ctx_priv_map_t *)data, + DRM_COPY_FROM_USER_IOCTL( 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__ + DRM_LOCK; TAILQ_FOREACH(list, dev->maplist, link) { map=list->map; - if(map->handle == request.handle) - goto found; + if(map->handle == request.handle) { + if (dev->max_context < 0) + goto bad; + if (request.ctx_id >= (unsigned) dev->max_context) + goto bad; + dev->context_sareas[request.ctx_id] = map; + DRM_UNLOCK; + return 0; + } } -#endif /* __FreeBSD__ */ bad: - DRM_OS_UNLOCK; - return DRM_OS_ERR(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; + DRM_UNLOCK; + return DRM_ERR(EINVAL); } /* ================================================================ @@ -237,7 +210,7 @@ int DRM(context_switch)( drm_device_t *dev, int old, int new ) if ( test_and_set_bit( 0, &dev->context_flag ) ) { DRM_ERROR( "Reentering -- FIXME\n" ); - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } #if __HAVE_DMA_HISTOGRAM @@ -279,41 +252,41 @@ int DRM(context_switch_complete)( drm_device_t *dev, int new ) #endif clear_bit( 0, &dev->context_flag ); - DRM_OS_WAKEUP( &dev->context_wait ); + DRM_WAKEUP( (void *)&dev->context_wait ); return 0; } -int DRM(resctx)( DRM_OS_IOCTL ) +int DRM(resctx)( DRM_IOCTL_ARGS ) { drm_ctx_res_t res; drm_ctx_t ctx; int i; - DRM_OS_KRNFROMUSR( res, (drm_ctx_res_t *)data, sizeof(res) ); + DRM_COPY_FROM_USER_IOCTL( 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], + if ( DRM_COPY_TO_USER( &res.contexts[i], &i, sizeof(i) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); } } res.count = DRM_RESERVED_CONTEXTS; - DRM_OS_KRNTOUSR( (drm_ctx_res_t *)data, res, sizeof(res) ); + DRM_COPY_TO_USER_IOCTL( (drm_ctx_res_t *)data, res, sizeof(res) ); return 0; } -int DRM(addctx)( DRM_OS_IOCTL ) +int DRM(addctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); ctx.handle = DRM(ctxbitmap_next)( dev ); if ( ctx.handle == DRM_KERNEL_CONTEXT ) { @@ -324,51 +297,51 @@ int DRM(addctx)( DRM_OS_IOCTL ) if ( ctx.handle == -1 ) { DRM_DEBUG( "Not enough free contexts.\n" ); /* Should this return -EBUSY instead? */ - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } - DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) ); + DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) ); return 0; } -int DRM(modctx)( DRM_OS_IOCTL ) +int DRM(modctx)( DRM_IOCTL_ARGS ) { /* This does nothing */ return 0; } -int DRM(getctx)( DRM_OS_IOCTL ) +int DRM(getctx)( DRM_IOCTL_ARGS ) { drm_ctx_t ctx; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); /* This is 0, because we don't handle any context flags */ ctx.flags = 0; - DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) ); + DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) ); return 0; } -int DRM(switchctx)( DRM_OS_IOCTL ) +int DRM(switchctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG( "%d\n", ctx.handle ); return DRM(context_switch)( dev, dev->last_context, ctx.handle ); } -int DRM(newctx)( DRM_OS_IOCTL ) +int DRM(newctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG( "%d\n", ctx.handle ); DRM(context_switch_complete)( dev, ctx.handle ); @@ -376,19 +349,14 @@ int DRM(newctx)( DRM_OS_IOCTL ) return 0; } -int DRM(rmctx)( DRM_OS_IOCTL ) +int DRM(rmctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( 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 ); } @@ -415,7 +383,7 @@ int DRM(context_switch)(drm_device_t *dev, int old, int new) if (test_and_set_bit(0, &dev->context_flag)) { DRM_ERROR("Reentering -- FIXME\n"); - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } #if __HAVE_DMA_HISTOGRAM @@ -426,7 +394,7 @@ int DRM(context_switch)(drm_device_t *dev, int old, int new) if (new >= dev->queue_count) { clear_bit(0, &dev->context_flag); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if (new == dev->last_context) { @@ -439,7 +407,7 @@ int DRM(context_switch)(drm_device_t *dev, int old, int new) if (atomic_read(&q->use_count) == 1) { atomic_dec(&q->use_count); clear_bit(0, &dev->context_flag); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if (DRM(flags) & DRM_FLAG_NOCTX) { @@ -478,7 +446,7 @@ int DRM(context_switch_complete)(drm_device_t *dev, int new) #endif clear_bit(0, &dev->context_flag); - DRM_OS_WAKEUP_INT(&dev->context_wait); + DRM_WAKEUP_INT(&dev->context_wait); return 0; } @@ -504,16 +472,9 @@ static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx) 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; @@ -549,7 +510,7 @@ static int DRM(alloc_queue)(drm_device_t *dev) atomic_dec(&dev->queuelist[i]->use_count); } /* Allocate a new queue */ - DRM_OS_LOCK; + DRM_LOCK; queue = gamma_alloc(sizeof(*queue), DRM_MEM_QUEUES); memset(queue, 0, sizeof(*queue)); @@ -567,19 +528,19 @@ static int DRM(alloc_queue)(drm_device_t *dev) newslots, DRM_MEM_QUEUES); if (!dev->queuelist) { - DRM_OS_UNLOCK; + DRM_UNLOCK; DRM_DEBUG("out of memory\n"); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } } dev->queuelist[dev->queue_count-1] = queue; - DRM_OS_UNLOCK; + DRM_UNLOCK; DRM_DEBUG("%d (new)\n", dev->queue_count - 1); return dev->queue_count - 1; } -int DRM(resctx)( DRM_OS_IOCTL ) +int DRM(resctx)( DRM_IOCTL_ARGS ) { drm_ctx_res_t res; drm_ctx_t ctx; @@ -587,31 +548,31 @@ int DRM(resctx)( DRM_OS_IOCTL ) DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); - DRM_OS_KRNFROMUSR( res, (drm_ctx_res_t *)data, sizeof(res) ); + DRM_COPY_FROM_USER_IOCTL( 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], + if (DRM_COPY_TO_USER(&res.contexts[i], &i, sizeof(i))) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); } } res.count = DRM_RESERVED_CONTEXTS; - DRM_OS_KRNTOUSR( (drm_ctx_res_t *)data, res, sizeof(res) ); + DRM_COPY_TO_USER_IOCTL( (drm_ctx_res_t *)data, res, sizeof(res) ); return 0; } -int DRM(addctx)( DRM_OS_IOCTL ) +int DRM(addctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( 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. */ @@ -621,35 +582,35 @@ int DRM(addctx)( DRM_OS_IOCTL ) 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) ); + DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) ); return 0; } -int DRM(modctx)( DRM_OS_IOCTL ) +int DRM(modctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; drm_queue_t *q; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG("%d\n", ctx.handle); if (ctx.handle < 0 || ctx.handle >= dev->queue_count) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if (DRM_BUFCOUNT(&q->waitlist)) { atomic_dec(&q->use_count); - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } q->flags = ctx.flags; @@ -658,52 +619,52 @@ int DRM(modctx)( DRM_OS_IOCTL ) return 0; } -int DRM(getctx)( DRM_OS_IOCTL ) +int DRM(getctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; drm_queue_t *q; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG("%d\n", ctx.handle); if (ctx.handle >= dev->queue_count) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } ctx.flags = q->flags; atomic_dec(&q->use_count); - DRM_OS_KRNTOUSR( (drm_ctx_t *)data, ctx, sizeof(ctx) ); + DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) ); return 0; } -int DRM(switchctx)( DRM_OS_IOCTL ) +int DRM(switchctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG("%d\n", ctx.handle); return DRM(context_switch)(dev, dev->last_context, ctx.handle); } -int DRM(newctx)( DRM_OS_IOCTL ) +int DRM(newctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG("%d\n", ctx.handle); DRM(context_switch_complete)(dev, ctx.handle); @@ -711,25 +672,25 @@ int DRM(newctx)( DRM_OS_IOCTL ) return 0; } -int DRM(rmctx)( DRM_OS_IOCTL ) +int DRM(rmctx)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_ctx_t ctx; drm_queue_t *q; drm_buf_t *buf; - DRM_OS_KRNFROMUSR( ctx, (drm_ctx_t *)data, sizeof(ctx) ); + DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) ); DRM_DEBUG("%d\n", ctx.handle); - if (ctx.handle >= dev->queue_count) return DRM_OS_ERR(EINVAL); + if (ctx.handle >= dev->queue_count) return DRM_ERR(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); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } atomic_inc(&q->finalization); /* Mark queue in finalization state */ @@ -737,20 +698,11 @@ int DRM(rmctx)( DRM_OS_IOCTL ) finalization) */ while (test_and_set_bit(0, &dev->interrupt_flag)) { -#ifdef __linux__ - schedule(); - if (signal_pending(current)) { - clear_bit(0, &dev->interrupt_flag); - return DRM_OS_ERR(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))) { @@ -759,15 +711,9 @@ int DRM(rmctx)( DRM_OS_IOCTL ) 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 ); + DRM_WAKEUP_INT( &q->flush_queue ); /* Finalization over. Queue is made available when both use_count and finalization become 0, which won't diff --git a/sys/dev/drm/drm_dma.h b/sys/dev/drm/drm_dma.h index 0ca180b..7ae0f5e 100644 --- a/sys/dev/drm/drm_dma.h +++ b/sys/dev/drm/drm_dma.h @@ -31,16 +31,6 @@ * $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 @@ -53,12 +43,6 @@ #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 ) @@ -67,7 +51,7 @@ int DRM(dma_setup)( drm_device_t *dev ) dev->dma = DRM(alloc)( sizeof(*dev->dma), DRM_MEM_DRIVER ); if ( !dev->dma ) - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); memset( dev->dma, 0, sizeof(*dev->dma) ); @@ -93,8 +77,8 @@ void DRM(dma_takedown)(drm_device_t *dev) 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(free)((void *)dma->bufs[i].seglist[j], + dma->bufs[i].buf_size, DRM_MEM_DMA); } DRM(free)(dma->bufs[i].seglist, @@ -204,17 +188,10 @@ void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf) 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 ); + wakeup( (void *)&buf->dma_wait ); buf->dma_wait = 0; } -#endif /* __FreeBSD__ */ #if __HAVE_DMA_FREELIST else { drm_device_dma_t *dma = dev->dma; @@ -263,7 +240,7 @@ void DRM(clear_next_buffer)(drm_device_t *dev) dma->next_buffer = NULL; if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) { - DRM_OS_WAKEUP_INT(&dma->next_queue->flush_queue); + DRM_WAKEUP_INT(&dma->next_queue->flush_queue); } dma->next_queue = NULL; } @@ -322,16 +299,6 @@ int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long)) && 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, @@ -340,7 +307,6 @@ int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long)) dev); } splx(s); -#endif /* __FreeBSD__ */ return -1; } @@ -356,12 +322,7 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d) 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); @@ -371,7 +332,7 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d) if (!_DRM_LOCK_IS_HELD(context)) { DRM_ERROR("No lock held during \"while locked\"" " request\n"); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if (d->context != _DRM_LOCKING_CONTEXT(context) && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) { @@ -379,7 +340,7 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d) " \"while locked\" request\n", _DRM_LOCKING_CONTEXT(context), d->context); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } q = dev->queuelist[DRM_KERNEL_CONTEXT]; while_locked = 1; @@ -390,24 +351,6 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d) 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); - return DRM_OS_ERR(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; @@ -419,7 +362,6 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d) } } atomic_dec(&q->block_count); -#endif /* __FreeBSD__ */ } for (i = 0; i < d->send_count; i++) { @@ -428,19 +370,19 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d) atomic_dec(&q->use_count); DRM_ERROR("Index %d (of %d max)\n", d->send_indices[i], dma->buf_count - 1); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } buf = dma->buflist[ idx ]; - if (buf->pid != DRM_OS_CURRENTPID) { + if (buf->pid != DRM_CURRENTPID) { atomic_dec(&q->use_count); DRM_ERROR("Process %d using buffer owned by %d\n", - DRM_OS_CURRENTPID, buf->pid); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid); + return DRM_ERR(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); + DRM_CURRENTPID, buf->idx, buf->list); } buf->used = d->send_sizes[i]; buf->while_locked = while_locked; @@ -453,14 +395,14 @@ int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d) DRM_ERROR("Queueing pending buffer:" " buffer %d, offset %d\n", d->send_indices[i], i); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if (buf->waiting) { atomic_dec(&q->use_count); DRM_ERROR("Queueing waiting buffer:" " buffer %d, offset %d\n", d->send_indices[i], i); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } buf->waiting = 1; if (atomic_read(&q->use_count) == 1 @@ -494,16 +436,16 @@ static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d, buf->waiting, buf->pending); } - buf->pid = DRM_OS_CURRENTPID; - if (DRM_OS_COPYTOUSR(&d->request_indices[i], + buf->pid = DRM_CURRENTPID; + if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); - if (DRM_OS_COPYTOUSR(&d->request_sizes[i], + if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); ++d->granted_count; } @@ -557,23 +499,20 @@ int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma) int DRM(irq_install)( drm_device_t *dev, int irq ) { -#ifdef __FreeBSD__ - int rid; -#endif /* __FreeBSD__ */ int retcode; if ( !irq ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); - DRM_OS_LOCK; + DRM_LOCK; if ( dev->irq ) { - DRM_OS_UNLOCK; - return DRM_OS_ERR(EBUSY); + DRM_UNLOCK; + return DRM_ERR(EBUSY); } dev->irq = irq; - DRM_OS_UNLOCK; + DRM_UNLOCK; - DRM_DEBUG( "%s: irq=%d\n", __func__, irq ); + DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq ); dev->context_flag = 0; dev->interrupt_flag = 0; @@ -584,48 +523,59 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) 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 + +#if __HAVE_VBL_IRQ && 0 /* disabled */ + DRM_SPININIT( dev->vbl_lock, "vblsig" ); + TAILQ_INIT( &dev->vbl_sig_list ); #endif /* Before installing handler */ - DRIVER_PREINSTALL(); + DRM(driver_irq_preinstall)( dev ); /* Install handler */ -#ifdef __linux__ - retcode = request_irq( dev->irq, DRM(dma_service), - DRM_IRQ_TYPE, dev->devname, dev ); - if ( retcode < 0 ) { -#endif /* __linux__ */ + dev->irqrid = 0; #ifdef __FreeBSD__ - rid = 0; - dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &rid, + dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &dev->irqrid, 0, ~0, 1, RF_SHAREABLE); - if (!dev->irqr) + if (!dev->irqr) { +#elif defined(__NetBSD__) + if (pci_intr_map(&dev->pa, &dev->ih) != 0) { +#endif + DRM_LOCK; + dev->irq = 0; + dev->irqrid = 0; + DRM_UNLOCK; return ENOENT; + } +#ifdef __FreeBSD__ +#if __FreeBSD_version < 500000 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY, DRM(dma_service), dev, &dev->irqh); +#else + retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE, + DRM(dma_service), dev, &dev->irqh); +#endif if ( retcode ) { -#endif /* __FreeBSD__ */ - DRM_OS_LOCK; +#elif defined(__NetBSD__) + dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY, + (int (*)(DRM_IRQ_ARGS))DRM(dma_service), dev); + if ( !dev->irqh ) { +#endif + DRM_LOCK; #ifdef __FreeBSD__ - bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr); -#endif /* __FreeBSD__ */ + bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr); +#endif dev->irq = 0; - DRM_OS_UNLOCK; + dev->irqrid = 0; + DRM_UNLOCK; return retcode; } /* After installing handler */ - DRIVER_POSTINSTALL(); + DRM(driver_irq_postinstall)( dev ); return 0; } @@ -633,36 +583,38 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) int DRM(irq_uninstall)( drm_device_t *dev ) { int irq; - - DRM_OS_LOCK; + int irqrid; + + DRM_LOCK; irq = dev->irq; + irqrid = dev->irqrid; dev->irq = 0; - DRM_OS_UNLOCK; + dev->irqrid = 0; + DRM_UNLOCK; if ( !irq ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); - DRM_DEBUG( "%s: irq=%d\n", __func__, irq ); + DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq ); - DRIVER_UNINSTALL(); + DRM(driver_irq_uninstall)( dev ); -#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__ */ - + bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr); +#elif defined(__NetBSD__) + pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh); +#endif + return 0; } -int DRM(control)( DRM_OS_IOCTL ) +int DRM(control)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_control_t ctl; - DRM_OS_KRNFROMUSR( ctl, (drm_control_t *) data, sizeof(ctl) ); + DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) ); switch ( ctl.func ) { case DRM_INST_HANDLER: @@ -670,10 +622,115 @@ int DRM(control)( DRM_OS_IOCTL ) case DRM_UNINST_HANDLER: return DRM(irq_uninstall)( dev ); default: - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); + } +} + +#if __HAVE_VBL_IRQ +int DRM(wait_vblank)( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_wait_vblank_t vblwait; + struct timeval now; + int ret; + + if (!dev->irq) + return DRM_ERR(EINVAL); + + DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data, + sizeof(vblwait) ); + + if (vblwait.request.type & _DRM_VBLANK_RELATIVE) { + vblwait.request.sequence += atomic_read(&dev->vbl_received); + vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; + } + + flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; + if (flags & _DRM_VBLANK_SIGNAL) { +#if 0 /* disabled */ + drm_vbl_sig_t *vbl_sig = DRM_MALLOC(sizeof(drm_vbl_sig_t)); + if (vbl_sig == NULL) + return ENOMEM; + bzero(vbl_sig, sizeof(*vbl_sig)); + + vbl_sig->sequence = vblwait.request.sequence; + vbl_sig->signo = vblwait.request.signal; + vbl_sig->pid = DRM_CURRENTPID; + + vblwait.reply.sequence = atomic_read(&dev->vbl_received); + + DRM_SPINLOCK(&dev->vbl_lock); + TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); + DRM_SPINUNLOCK(&dev->vbl_lock); + ret = 0; +#endif + ret = EINVAL; + } else { + ret = DRM(vblank_wait)(dev, &vblwait.request.sequence); + + microtime(&now); + vblwait.reply.tval_sec = now.tv_sec; + vblwait.reply.tval_usec = now.tv_usec; + } + + DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, + sizeof(vblwait) ); + + return ret; +} + +void DRM(vbl_send_signals)(drm_device_t *dev) +{ +} + +#if 0 /* disabled */ +void DRM(vbl_send_signals)( drm_device_t *dev ) +{ + drm_vbl_sig_t *vbl_sig; + unsigned int vbl_seq = atomic_read( &dev->vbl_received ); + struct proc *p; + + DRM_SPINLOCK(&dev->vbl_lock); + + vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); + while (vbl_sig != NULL) { + drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); + + if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { + p = pfind(vbl_sig->pid); + if (p != NULL) + psignal(p, vbl_sig->signo); + + TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); + DRM_FREE(vbl_sig,sizeof(*vbl_sig)); + } + vbl_sig = next; + } + + DRM_SPINUNLOCK(&dev->vbl_lock); +} +#endif + +#endif /* __HAVE_VBL_IRQ */ + +#else + +int DRM(control)( DRM_IOCTL_ARGS ) +{ + drm_control_t ctl; + + DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) ); + + switch ( ctl.func ) { + case DRM_INST_HANDLER: + case DRM_UNINST_HANDLER: + return 0; + default: + return DRM_ERR(EINVAL); } } #endif /* __HAVE_DMA_IRQ */ #endif /* __HAVE_DMA */ + diff --git a/sys/dev/drm/drm_drawable.h b/sys/dev/drm/drm_drawable.h index a071128..7f3938d 100644 --- a/sys/dev/drm/drm_drawable.h +++ b/sys/dev/drm/drm_drawable.h @@ -31,22 +31,21 @@ * $FreeBSD$ */ -#define __NO_VERSION__ #include "dev/drm/drmP.h" -int DRM(adddraw)( DRM_OS_IOCTL ) +int DRM(adddraw)( DRM_IOCTL_ARGS ) { drm_draw_t draw; draw.handle = 0; /* NOOP */ DRM_DEBUG("%d\n", draw.handle); - DRM_OS_KRNTOUSR( (drm_draw_t *)data, draw, sizeof(draw) ); + DRM_COPY_TO_USER_IOCTL( (drm_draw_t *)data, draw, sizeof(draw) ); return 0; } -int DRM(rmdraw)( DRM_OS_IOCTL ) +int DRM(rmdraw)( DRM_IOCTL_ARGS ) { return 0; /* NOOP */ } diff --git a/sys/dev/drm/drm_drv.h b/sys/dev/drm/drm_drv.h index b709d6f..7408367 100644 --- a/sys/dev/drm/drm_drv.h +++ b/sys/dev/drm/drm_drv.h @@ -118,31 +118,8 @@ #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> -#endif -#endif /* __FreeBSD__ */ #endif - /* * The default number of instances (minor numbers) to initialize. */ @@ -150,11 +127,10 @@ static struct file_operations DRM(fops) = { \ #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 +#ifdef __FreeBSD__ #define DRIVER_SOFTC(unit) \ ((drm_device_t *) devclass_get_softc(DRM(devclass), unit)) @@ -166,13 +142,10 @@ 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__ */ +#ifdef __NetBSD__ +#define DRIVER_SOFTC(unit) \ + ((drm_device_t *) device_lookup(&DRM(cd), unit)) +#endif /* __NetBSD__ */ static drm_ioctl_desc_t DRM(ioctls)[] = { [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 }, @@ -220,10 +193,8 @@ static drm_ioctl_desc_t DRM(ioctls)[] = { /* 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 }, @@ -236,49 +207,48 @@ static drm_ioctl_desc_t DRM(ioctls)[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 }, #endif -#if __REALLY_HAVE_SG +#if __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 +#if __HAVE_VBL_IRQ + [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { DRM(wait_vblank), 0, 0 }, +#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__ */ +const char *DRM(find_description)(int vendor, int device); #ifdef __FreeBSD__ +static struct cdevsw DRM(cdevsw) = { + .d_open = DRM( open ), + .d_close = DRM( close ), + .d_read = DRM( read ), + .d_write = DRM( write ), + .d_ioctl = DRM( ioctl ), + .d_poll = DRM( poll ), + .d_mmap = DRM( mmap ), + .d_name = DRIVER_NAME, + .d_maj = CDEV_MAJOR, + .d_flags = D_TTY | D_TRACKCLOSE, +#if __FreeBSD_version < 500000 + .d_bmaj = -1 +#endif +}; + static int DRM(probe)(device_t dev) { - const char *s = 0; + const char *s = NULL; 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++; - } + s = DRM(find_description)(vendor, device); if (s) { device_set_desc(dev, s); return 0; @@ -297,7 +267,6 @@ 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)), @@ -313,24 +282,150 @@ static driver_t DRM(driver) = { sizeof(drm_device_t), }; -static devclass_t DRM( devclass); +static devclass_t DRM(devclass); + +#elif defined(__NetBSD__) + +static struct cdevsw DRM(cdevsw) = { + DRM(open), + DRM(close), + DRM(read), + DRM(write), + DRM(ioctl), + nostop, + notty, + DRM(poll), + DRM(mmap), + nokqfilter, + D_TTY +}; -static struct cdevsw DRM( cdevsw) = { - .d_open = DRM( open ), - .d_close = DRM( close ), - .d_read = DRM( read ), - .d_write = DRM( write ), - .d_ioctl = DRM( ioctl ), - .d_poll = DRM( poll ), - .d_mmap = DRM( mmap ), - .d_name = DRIVER_NAME, - .d_maj = CDEV_MAJOR, - .d_flags = D_TTY | D_TRACKCLOSE, -#if __FreeBSD_version < 500000 - /* bmaj */ -1 +int DRM(refcnt) = 0; +#if __NetBSD_Version__ >= 106080000 +MOD_DEV( DRIVER_NAME, DRIVER_NAME, NULL, -1, &DRM(cdevsw), CDEV_MAJOR); +#else +MOD_DEV( DRIVER_NAME, LM_DT_CHAR, CDEV_MAJOR, &DRM(cdevsw) ); #endif -}; -#endif /* __FreeBSD__ */ + +int DRM(lkmentry)(struct lkm_table *lkmtp, int cmd, int ver); +static int DRM(lkmhandle)(struct lkm_table *lkmtp, int cmd); + +int DRM(modprobe)(); +int DRM(probe)(struct pci_attach_args *pa); +void DRM(attach)(struct pci_attach_args *pa, dev_t kdev); + +int DRM(lkmentry)(struct lkm_table *lkmtp, int cmd, int ver) { + DISPATCH(lkmtp, cmd, ver, DRM(lkmhandle), DRM(lkmhandle), DRM(lkmhandle)); +} + +static int DRM(lkmhandle)(struct lkm_table *lkmtp, int cmd) +{ + int j, error = 0; +#if defined(__NetBSD__) && (__NetBSD_Version__ > 106080000) + struct lkm_dev *args = lkmtp->private.lkm_dev; +#endif + + switch(cmd) { + case LKM_E_LOAD: + if (lkmexists(lkmtp)) + return EEXIST; + + if(DRM(modprobe)()) + return 0; + + return 1; + + case LKM_E_UNLOAD: + if (DRM(refcnt) > 0) + return (EBUSY); + break; + case LKM_E_STAT: + break; + + default: + error = EIO; + break; + } + + return error; +} + +int DRM(modprobe)() { + struct pci_attach_args pa; + int error = 0; + if((error = pci_find_device(&pa, DRM(probe))) != 0) + DRM(attach)(&pa, 0); + + return error; +} + +int DRM(probe)(struct pci_attach_args *pa) +{ + const char *desc; + + desc = DRM(find_description)(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)); + if (desc != NULL) { + return 1; + } + + return 0; +} + +void DRM(attach)(struct pci_attach_args *pa, dev_t kdev) +{ + int i; + drm_device_t *dev; + + config_makeroom(kdev, &DRM(cd)); + DRM(cd).cd_devs[(kdev)] = DRM(alloc)(sizeof(drm_device_t), + DRM_MEM_DRIVER); + dev = DRIVER_SOFTC(kdev); + + memset(dev, 0, sizeof(drm_device_t)); + memcpy(&dev->pa, pa, sizeof(dev->pa)); + + DRM_INFO("%s", DRM(find_description)(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id))); + DRM(init)(dev); +} + +int DRM(detach)(struct device *self, int flags) +{ + DRM(cleanup)((drm_device_t *)self); + return 0; +} + +int DRM(activate)(struct device *self, enum devact act) +{ + switch (act) { + case DVACT_ACTIVATE: + return (EOPNOTSUPP); + break; + + case DVACT_DEACTIVATE: + /* FIXME */ + break; + } + return (0); +} +#endif /* __NetBSD__ */ + +const char *DRM(find_description)(int vendor, int device) { + const char *s = NULL; + int i=0, done=0; + + 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++; + } + return s; +} static int DRM(setup)( drm_device_t *dev ) { @@ -396,24 +491,14 @@ static int DRM(setup)( drm_device_t *dev ) dev->maplist = DRM(alloc)(sizeof(*dev->maplist), DRM_MEM_MAPS); - if(dev->maplist == NULL) return DRM_OS_ERR(ENOMEM); + if(dev->maplist == NULL) return DRM_ERR(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; @@ -425,18 +510,12 @@ static int DRM(setup)( drm_device_t *dev ) 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; @@ -444,17 +523,14 @@ static int DRM(setup)( drm_device_t *dev ) 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; +#elif defined(__NetBSD__) + dev->buf_pgid = 0; +#endif dev->buf_readers = 0; dev->buf_writers = 0; dev->buf_selecting = 0; -#endif /* __FreeBSD__ */ DRM_DEBUG( "\n" ); @@ -472,14 +548,8 @@ static int DRM(setup)( drm_device_t *dev ) 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_local_map_t *map; drm_map_list_entry_t *list; -#endif /* __FreeBSD__ */ drm_vma_entry_t *vma, *vma_next; int i; @@ -490,13 +560,8 @@ static int DRM(takedown)( drm_device_t *dev ) if ( dev->irq ) DRM(irq_uninstall)( dev ); #endif - DRM_OS_LOCK; -#ifdef __linux__ - del_timer( &dev->timer ); -#endif /* __linux__ */ -#ifdef __FreeBSD__ + DRM_LOCK; callout_stop( &dev->timer ); -#endif /* __FreeBSD__ */ if ( dev->devname ) { DRM(free)( dev->devname, strlen( dev->devname ) + 1, @@ -529,14 +594,8 @@ static int DRM(takedown)( drm_device_t *dev ) 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; @@ -558,44 +617,43 @@ static int DRM(takedown)( drm_device_t *dev ) } 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 ); +#ifdef __FreeBSD__ + int act; + struct mem_range_desc mrdesc; + mrdesc.mr_base = map->offset; + mrdesc.mr_len = map->size; + mrdesc.mr_flags = MDF_WRITECOMBINE; + act = MEMRANGE_SET_UPDATE; + bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME)); + retcode = mem_range_attr_set(&mrdesc, &act); + map->mtrr=1; +#elif defined __NetBSD__ + struct mtrr mtrrmap; + int one = 1; + mtrrmap.base = map->offset; + mtrrmap.len = map->size; + mtrrmap.type = MTRR_TYPE_WC; + mtrrmap.flags = 0; + retcode = mtrr_set( &mtrrmap, &one, + DRM_CURPROC, MTRR_GETSET_KERNEL); +#endif DRM_DEBUG( "mtrr_del=%d\n", retcode ); } #endif - DRM(ioremapfree)( map->handle, map->size ); + DRM(ioremapfree)( map ); 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(free)(map->handle, + map->size, DRM_MEM_SAREA); -#endif /* __FreeBSD__ */ break; case _DRM_AGP: @@ -615,10 +673,8 @@ static int DRM(takedown)( drm_device_t *dev ) #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); @@ -650,261 +706,184 @@ static int DRM(takedown)( drm_device_t *dev ) 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_WAKEUP_INT((void *)&dev->lock.lock_queue); } - DRM_OS_UNLOCK; + DRM_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). +/* linux: drm_init is called via init_module at module load time, or via + * linux/init/main.c (this is not currently supported). + * bsd: drm_init is called via the attach function per device. */ -#ifdef __linux__ -static int __init drm_init( void ) -#endif /* __linux__ */ -#ifdef __FreeBSD__ static int DRM(init)( device_t nbdev ) -#endif /* __FreeBSD__ */ { - + int unit; +#ifdef __FreeBSD__ drm_device_t *dev; - int i; +#elif defined(__NetBSD__) + drm_device_t *dev = nbdev; +#endif #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)) { - return DRM_OS_ERR(ENOMEM); - } - DRM(minor) = DRM_OS_MALLOC(sizeof(*(DRM(minor))) * DRM(numdevs)); - if (!DRM(minor)) { - DRM_OS_FREE(DRM(device)); - return DRM_OS_ERR(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__ */ + unit = device_get_unit(nbdev); + dev = device_get_softc(nbdev); + memset( (void *)dev, 0, sizeof(*dev) ); + dev->device = nbdev; + dev->devnode = make_dev( &DRM(cdevsw), + unit, + DRM_DEV_UID, + DRM_DEV_GID, + DRM_DEV_MODE, + "dri/card%d", unit ); +#elif defined(__NetBSD__) + unit = minor(dev->device.dv_unit); +#endif + DRM_SPININIT(dev->count_lock, "drm device"); + lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0); + dev->name = DRIVER_NAME; + DRM(mem_init)(); + DRM(sysctl_init)(dev); + TAILQ_INIT(&dev->files); #if __REALLY_HAVE_AGP - dev->agp = DRM(agp_init)(); + 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__ */ + if ( dev->agp == NULL ) { + DRM_ERROR( "Cannot initialize the agpgart module.\n" ); + DRM(sysctl_cleanup)( dev ); #ifdef __FreeBSD__ - DRM(sysctl_cleanup)( dev ); - destroy_dev(dev->devnode); -#endif /* __FreeBSD__ */ - DRM(takedown)( dev ); - return DRM_OS_ERR(ENOMEM); - } + destroy_dev(dev->devnode); #endif + DRM(takedown)( dev ); + return DRM_ERR(ENOMEM); + } +#endif /* __MUST_HAVE_AGP */ #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 (dev->agp) { +#ifdef __FreeBSD__ + int retcode = 0, act; + struct mem_range_desc mrdesc; + mrdesc.mr_base = dev->agp->info.ai_aperture_base; + mrdesc.mr_len = dev->agp->info.ai_aperture_size; + mrdesc.mr_flags = MDF_WRITECOMBINE; + act = MEMRANGE_SET_UPDATE; + bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME)); + retcode = mem_range_attr_set(&mrdesc, &act); + dev->agp->agp_mtrr=1; +#elif defined __NetBSD__ + struct mtrr mtrrmap; + int one = 1; + mtrrmap.base = dev->agp->info.ai_aperture_base; + mtrrmap.len = dev->agp->info.ai_aperture_size; + mtrrmap.type = MTRR_TYPE_WC; + mtrrmap.flags = MTRR_VALID; + dev->agp->agp_mtrr = mtrr_set( &mtrrmap, &one, NULL, MTRR_GETSET_KERNEL); +#endif /* __NetBSD__ */ + } +#endif /* __REALLY_HAVE_MTRR */ +#endif /* __REALLY_HAVE_AGP */ #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__ */ + retcode = DRM(ctxbitmap_init)( dev ); + if( retcode ) { + DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); + DRM(sysctl_cleanup)( dev ); #ifdef __FreeBSD__ - DRM(sysctl_cleanup)( dev ); - destroy_dev(dev->devnode); -#endif /* __FreeBSD__ */ - DRM(takedown)( dev ); - return retcode; - } + destroy_dev(dev->devnode); #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] ); + 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, + unit ); DRIVER_POSTINIT(); return 0; } -/* drm_cleanup is called via cleanup_module at module unload time. +/* linux: drm_cleanup is called via cleanup_module at module unload time. + * bsd: drm_cleanup is called per device at module unload time. + * FIXME: NetBSD */ -#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; +#ifdef __NetBSD__ +#if __REALLY_HAVE_MTRR + struct mtrr mtrrmap; + int one = 1; +#endif /* __REALLY_HAVE_MTRR */ + dev = nbdev; +#endif /* __NetBSD__ */ 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__ */ + dev = device_get_softc(nbdev); +#endif + DRM(sysctl_cleanup)( dev ); +#ifdef __FreeBSD__ + destroy_dev(dev->devnode); +#endif #if __HAVE_CTX_BITMAP - DRM(ctxbitmap_cleanup)( dev ); + 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 ); - } + if ( dev->agp && dev->agp->agp_mtrr >= 0) { +#if defined(__NetBSD__) + mtrrmap.base = dev->agp->info.ai_aperture_base; + mtrrmap.len = dev->agp->info.ai_aperture_size; + mtrrmap.type = 0; + mtrrmap.flags = 0; + mtrr_set( &mtrrmap, &one, NULL, MTRR_GETSET_KERNEL); +#endif + } #endif - DRM(takedown)( dev ); + 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 + 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; + DRM(mem_uninit)(); + DRM_SPINUNINIT(dev->count_lock); } -#ifdef __linux__ -module_init( drm_init ); -module_exit( drm_cleanup ); -#endif /* __linux__ */ -int DRM(version)( DRM_OS_IOCTL ) +int DRM(version)( DRM_IOCTL_ARGS ) { drm_version_t version; int len; - DRM_OS_KRNFROMUSR( version, (drm_version_t *)data, sizeof(version) ); + DRM_COPY_FROM_USER_IOCTL( 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 ) ) \ - return DRM_OS_ERR(EFAULT); \ + if ( DRM_COPY_TO_USER( name, value, len ) ) \ + return DRM_ERR(EFAULT); \ } version.version_major = DRIVER_MAJOR; @@ -915,90 +894,48 @@ int DRM(version)( DRM_OS_IOCTL ) DRM_COPY( version.date, DRIVER_DATE ); DRM_COPY( version.desc, DRIVER_DESC ); - DRM_OS_KRNTOUSR( (drm_version_t *)data, version, sizeof(version) ); + DRM_COPY_TO_USER_IOCTL( (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__ */ +int DRM(open)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p) { 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) { - return DRM_OS_ERR(ENODEV); - } + dev = DRIVER_SOFTC(minor(kdev)); 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 ); - } + DRM_SPINLOCK( &dev->count_lock ); #ifdef __FreeBSD__ - device_unbusy(dev->device); -#endif /* __FreeBSD__ */ + device_busy(dev->device); +#endif + if ( !dev->open_count++ ) + retcode = DRM(setup)( dev ); + DRM_SPINUNLOCK( &dev->count_lock ); + } 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) +int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p) { drm_file_t *priv; - drm_device_t *dev = kdev->si_drv1; -#endif /* __FreeBSD__ */ + DRM_DEVICE; 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(); @@ -1006,13 +943,18 @@ int DRM( close)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p) * Begin inline drm_release */ +#ifdef __FreeBSD__ DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n", - DRM_OS_CURRENTPID, (long)dev->device, dev->open_count ); + DRM_CURRENTPID, (long)dev->device, dev->open_count ); +#elif defined(__NetBSD__) + DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n", + DRM_CURRENTPID, (long)&dev->device, dev->open_count); +#endif if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) - && dev->lock.pid == DRM_OS_CURRENTPID) { + && dev->lock.pid == DRM_CURRENTPID) { DRM_DEBUG("Process %d dead, freeing lock for context %d\n", - DRM_OS_CURRENTPID, + DRM_CURRENTPID, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); #if HAVE_DRIVER_RELEASE DRIVER_RELEASE(); @@ -1029,27 +971,15 @@ int DRM( close)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p) #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 = DRM_OS_ERR(EINTR); + retcode = DRM_ERR(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.pid = DRM_CURRENTPID; dev->lock.lock_time = jiffies; atomic_inc( &dev->counts[_DRM_STAT_LOCKS] ); break; /* Got lock */ @@ -1058,26 +988,13 @@ int DRM( close)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p) #if 0 atomic_inc( &dev->total_sleeps ); #endif -#ifdef __linux__ - schedule(); - if ( signal_pending( current ) ) { - retcode = DRM_OS_ERR(ERESTARTSYS); - break; - } -#endif /* __linux__ */ -#ifdef __FreeBSD__ - retcode = tsleep(&dev->lock.lock_queue, + retcode = tsleep((void *)&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, @@ -1088,100 +1005,74 @@ int DRM( close)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p) DRM(reclaim_buffers)( dev, priv->pid ); #endif -#ifdef __linux__ - DRM(fasync)( -1, filp, 0 ); -#endif /* __linux__ */ -#ifdef __FreeBSD__ +#if defined (__FreeBSD__) && (__FreeBSD_version >= 500000) funsetown(&dev->buf_sigio); -#endif /* __FreeBSD__ */ +#elif defined(__FreeBSD__) + funsetown(dev->buf_sigio); +#elif defined(__NetBSD__) + dev->buf_pgid = 0; +#endif /* __NetBSD__ */ - 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__ + DRM_LOCK; priv = DRM(find_file_by_proc)(dev, p); if (priv) { priv->refs--; if (!priv->refs) { TAILQ_REMOVE(&dev->files, priv, link); + DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES ); } } -#endif /* __FreeBSD__ */ - DRM_OS_UNLOCK; + DRM_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 ); + DRM_SPINLOCK( &dev->count_lock ); +#ifdef __FreeBSD__ + device_unbusy(dev->device); +#endif 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__ */ - return DRM_OS_ERR(EBUSY); + DRM_SPINUNLOCK( &dev->count_lock ); + return DRM_ERR(EBUSY); } - DRM_OS_SPINUNLOCK( &dev->count_lock ); -#ifdef __linux__ - unlock_kernel(); -#endif /* __linux__ */ -#ifdef __FreeBSD__ - device_unbusy(dev->device); -#endif /* __FreeBSD__ */ + DRM_SPINUNLOCK( &dev->count_lock ); return DRM(takedown)( dev ); } - DRM_OS_SPINUNLOCK( &dev->count_lock ); - -#ifdef __linux__ - unlock_kernel(); -#endif /* __linux__ */ + DRM_SPINUNLOCK( &dev->count_lock ); return retcode; } /* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm. */ -int DRM(ioctl)( DRM_OS_IOCTL ) +int DRM(ioctl)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; int retcode = 0; drm_ioctl_desc_t *ioctl; - drm_ioctl_t *func; + d_ioctl_t *func; int nr = DRM_IOCTL_NR(cmd); - DRM_OS_PRIV; + DRM_PRIV; atomic_inc( &dev->ioctl_count ); atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] ); ++priv->ioctl_count; +#ifdef __FreeBSD__ 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 ); + DRM_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated ); +#elif defined(__NetBSD__) + DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n", + DRM_CURRENTPID, cmd, nr, (long)&dev->device, priv->authenticated ); +#endif -#ifdef __FreeBSD__ switch (cmd) { case FIONBIO: atomic_dec(&dev->ioctl_count); @@ -1192,44 +1083,57 @@ int DRM(ioctl)( DRM_OS_IOCTL ) dev->flags |= FASYNC; return 0; +#ifdef __FreeBSD__ case FIOSETOWN: atomic_dec(&dev->ioctl_count); return fsetown(*(int *)data, &dev->buf_sigio); case FIOGETOWN: atomic_dec(&dev->ioctl_count); +#if (__FreeBSD_version >= 500000) *(int *) data = fgetown(&dev->buf_sigio); +#else + *(int *) data = fgetown(dev->buf_sigio); +#endif return 0; - } #endif /* __FreeBSD__ */ +#ifdef __NetBSD__ + case TIOCSPGRP: + atomic_dec(&dev->ioctl_count); + dev->buf_pgid = *(int *)data; + return 0; + + case TIOCGPGRP: + atomic_dec(&dev->ioctl_count); + *(int *)data = dev->buf_pgid; + return 0; +#endif /* __NetBSD__ */ + } if ( nr >= DRIVER_IOCTL_COUNT ) { - retcode = DRM_OS_ERR(EINVAL); + retcode = EINVAL; } else { ioctl = &DRM(ioctls)[nr]; func = ioctl->func; if ( !func ) { DRM_DEBUG( "no function\n" ); - retcode = DRM_OS_ERR(EINVAL); - } else if ( ( ioctl->root_only && DRM_OS_CHECKSUSER ) + retcode = EINVAL; + } else if ( ( ioctl->root_only && DRM_SUSER(p) ) || ( ioctl->auth_needed && !priv->authenticated ) ) { - retcode = DRM_OS_ERR(EACCES); + retcode = EACCES; } else { - retcode = func( IOCTL_ARGS_PASS ); + retcode = func( kdev, cmd, data, flags, p ); } } atomic_dec( &dev->ioctl_count ); - return retcode; + return DRM_ERR(retcode); } -int DRM(lock)( DRM_OS_IOCTL ) +int DRM(lock)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; -#ifdef __linux__ - DECLARE_WAITQUEUE( entry, current ); -#endif /* __linux__ */ + DRM_DEVICE; drm_lock_t lock; int ret = 0; #if __HAVE_MULTIPLE_DMA_QUEUES @@ -1241,24 +1145,24 @@ int DRM(lock)( DRM_OS_IOCTL ) dev->lck_start = start = get_cycles(); #endif - DRM_OS_KRNFROMUSR( lock, (drm_lock_t *)data, sizeof(lock) ); + DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) ); if ( lock.context == DRM_KERNEL_CONTEXT ) { DRM_ERROR( "Process %d using kernel context %d\n", - DRM_OS_CURRENTPID, lock.context ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, lock.context ); + return DRM_ERR(EINVAL); } DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", - lock.context, DRM_OS_CURRENTPID, + lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock, lock.flags ); #if __HAVE_DMA_QUEUE if ( lock.context < 0 ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); #elif __HAVE_MULTIPLE_DMA_QUEUES if ( lock.context < 0 || lock.context >= dev->queue_count ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); q = dev->queuelist[lock.context]; #endif @@ -1266,47 +1170,28 @@ int DRM(lock)( DRM_OS_IOCTL ) 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 = DRM_OS_ERR(EINTR); + ret = EINTR; break; } if ( DRM(lock_take)( &dev->lock.hw_lock->lock, lock.context ) ) { - dev->lock.pid = DRM_OS_CURRENTPID; + dev->lock.pid = DRM_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 = DRM_OS_ERR(ERESTARTSYS); - break; - } -#endif /* __linux__ */ -#ifdef __FreeBSD__ - ret = tsleep(&dev->lock.lock_queue, + ret = tsleep((void *)&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 @@ -1314,17 +1199,6 @@ int DRM(lock)( DRM_OS_IOCTL ) #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 ) { @@ -1350,21 +1224,21 @@ int DRM(lock)( DRM_OS_IOCTL ) atomic_inc(&dev->histo.lacq[DRM(histogram_slot)(get_cycles()-start)]); #endif - return ret; + return DRM_ERR(ret); } -int DRM(unlock)( DRM_OS_IOCTL ) +int DRM(unlock)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_lock_t lock; - DRM_OS_KRNFROMUSR( lock, (drm_lock_t *)data, sizeof(lock) ) ; + DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) ) ; if ( lock.context == DRM_KERNEL_CONTEXT ) { DRM_ERROR( "Process %d using kernel context %d\n", - DRM_OS_CURRENTPID, lock.context ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, lock.context ); + return DRM_ERR(EINVAL); } atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] ); @@ -1394,7 +1268,7 @@ int DRM(unlock)( DRM_OS_IOCTL ) DRM(dma_schedule)( dev, 1 ); #endif - /* FIXME: Do we ever really need to check this??? + /* FIXME: Do we ever really need to check this? */ if ( 1 /* !dev->context_flag */ ) { if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock, @@ -1404,9 +1278,6 @@ int DRM(unlock)( DRM_OS_IOCTL ) } #endif /* !__HAVE_KERNEL_CTX_SWITCH */ -#ifdef __linux__ - unblock_all_signals(); -#endif /* __linux__ */ return 0; } @@ -1427,7 +1298,7 @@ SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_ * Linux emulation IOCTL */ static int -DRM(linux_ioctl)(DRM_OS_STRUCTPROC *p, struct linux_ioctl_args* args) +DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args) { u_long cmd = args->cmd; #define STK_PARAMS 128 diff --git a/sys/dev/drm/drm_fops.h b/sys/dev/drm/drm_fops.h index 081027d..136f4d6 100644 --- a/sys/dev/drm/drm_fops.h +++ b/sys/dev/drm/drm_fops.h @@ -32,18 +32,9 @@ * $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) +drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_STRUCTPROC *p) { #if __FreeBSD_version >= 500021 uid_t uid = p->td_proc->p_ucred->cr_svuid; @@ -59,64 +50,24 @@ drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_OS_STRUCTPROC *p) 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, +int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_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)()) - return DRM_OS_ERR(EINVAL); - - DRM_DEBUG("pid = %d, minor = %d\n", DRM_OS_CURRENTPID, m); + return DRM_ERR(EINVAL); -#ifdef __linux__ - priv = (drm_file_t *) DRM(alloc)(sizeof(*priv), DRM_MEM_FILES); - if(!priv) return DRM_OS_ERR(ENOMEM); + DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m); - 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++; @@ -135,93 +86,35 @@ int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p, priv->minor = m; priv->devXX = dev; priv->ioctl_count = 0; - priv->authenticated = !DRM_OS_CHECKSUSER; - lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, p); + priv->authenticated = !DRM_SUSER(p); + DRM_LOCK; TAILQ_INSERT_TAIL(&dev->files, priv, link); - lockmgr(&dev->dev_lock, LK_RELEASE, 0, p); + DRM_UNLOCK; } - +#ifdef __FreeBSD__ 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__ */ +int DRM(read)(dev_t kdev, struct uio *uio, int ioflag) { - DRM_OS_DEVICE; + DRM_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); @@ -229,18 +122,12 @@ ssize_t DRM(read)(dev_t kdev, struct uio *uio, int ioflag) 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) { @@ -248,28 +135,16 @@ ssize_t DRM(read)(dev_t kdev, struct uio *uio, int ioflag) } 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) @@ -277,6 +152,9 @@ 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; +#ifdef __NetBSD__ + struct proc *p; +#endif /* __NetBSD__ */ DRM_DEBUG("%d left, %d to send (%p, %p)\n", left, send, dev->buf_rp, dev->buf_wp); @@ -301,43 +179,40 @@ int DRM(write_string)(drm_device_t *dev, const char *s) 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); } +#ifdef __FreeBSD__ 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); +#if __FreeBSD_version >= 500000 pgsigio(&dev->buf_sigio, SIGIO, 0); +#else + pgsigio(dev->buf_sigio, SIGIO, 0); +#endif /* __FreeBSD_version */ + } +#endif /* __FreeBSD__ */ +#ifdef __NetBSD__ + if (dev->buf_pgid) { + DRM_DEBUG("dev->buf_pgid=%d\n", dev->buf_pgid); + if(dev->buf_pgid > 0) + gsignal(dev->buf_pgid, SIGIO); + else if(dev->buf_pgid && (p = pfind(-dev->buf_pgid)) != NULL) + psignal(p, SIGIO); } +#endif /* __NetBSD__ */ 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) +int DRM(poll)(dev_t kdev, int events, DRM_STRUCTPROC *p) { - 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; + DRM_DEVICE; int s; int revents = 0; @@ -356,8 +231,15 @@ int DRM(poll)(dev_t kdev, int events, DRM_OS_STRUCTPROC *p) 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; +#if DRM_DEBUG_CODE + DRM_DEVICE; +#endif +#ifdef __FreeBSD__ + DRM_DEBUG("pid = %d, device = %p, open_count = %d\n", + curproc->p_pid, dev->device, dev->open_count); +#elif defined(__NetBSD__) + DRM_DEBUG("pid = %d, device = %p, open_count = %d\n", + curproc->p_pid, &dev->device, dev->open_count); +#endif + return 0; } -#endif /* __FreeBSD__ */ diff --git a/sys/dev/drm/drm_init.h b/sys/dev/drm/drm_init.h index 3839432..432225f 100644 --- a/sys/dev/drm/drm_init.h +++ b/sys/dev/drm/drm_init.h @@ -31,7 +31,6 @@ * $FreeBSD$ */ -#define __NO_VERSION__ #include "dev/drm/drmP.h" #if 1 && DRM_DEBUG_CODE @@ -108,13 +107,5 @@ void DRM(parse_options)(char *s) */ 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 index 3989a31..4826faf 100644 --- a/sys/dev/drm/drm_ioctl.h +++ b/sys/dev/drm/drm_ioctl.h @@ -31,34 +31,19 @@ * $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 ) +int DRM(irq_busid)( DRM_IOCTL_ARGS ) { - drm_irq_busid_t id; -#ifdef __linux__ - struct pci_dev *dev; -#endif /* __linux__ */ #ifdef __FreeBSD__ + drm_irq_busid_t id; 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) ); + DRM_COPY_FROM_USER_IOCTL( 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; @@ -83,53 +68,56 @@ int DRM(irq_busid)( DRM_OS_IOCTL ) 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) ); + DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, id, sizeof(id) ); return 0; +#else + /* don't support interrupt-driven drivers on Net yet */ + return ENOENT; +#endif } -int DRM(getunique)( DRM_OS_IOCTL ) +int DRM(getunique)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_unique_t u; - DRM_OS_KRNFROMUSR( u, (drm_unique_t *)data, sizeof(u) ); + DRM_COPY_FROM_USER_IOCTL( 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)) - return DRM_OS_ERR(EFAULT); + if (DRM_COPY_TO_USER(u.unique, dev->unique, dev->unique_len)) + return DRM_ERR(EFAULT); } u.unique_len = dev->unique_len; - DRM_OS_KRNTOUSR( (drm_unique_t *)data, u, sizeof(u) ); + DRM_COPY_TO_USER_IOCTL( (drm_unique_t *)data, u, sizeof(u) ); return 0; } -int DRM(setunique)( DRM_OS_IOCTL ) +int DRM(setunique)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_unique_t u; if (dev->unique_len || dev->unique) - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); - DRM_OS_KRNFROMUSR( u, (drm_unique_t *)data, sizeof(u) ); + DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) ); if (!u.unique_len || u.unique_len > 1024) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); dev->unique_len = u.unique_len; dev->unique = DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER); - if(!dev->unique) return DRM_OS_ERR(ENOMEM); + if(!dev->unique) return DRM_ERR(ENOMEM); - if (DRM_OS_COPYFROMUSR(dev->unique, u.unique, dev->unique_len)) - return DRM_OS_ERR(EFAULT); + if (DRM_COPY_FROM_USER(dev->unique, u.unique, dev->unique_len)) + return DRM_ERR(EFAULT); dev->unique[dev->unique_len] = '\0'; @@ -137,85 +125,34 @@ int DRM(setunique)( DRM_OS_IOCTL ) DRM_MEM_DRIVER); if(!dev->devname) { DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(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 ) +int DRM(getmap)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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_local_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) ); + DRM_COPY_FROM_USER_IOCTL( map, (drm_map_t *)data, sizeof(map) ); idx = map.offset; - DRM_OS_LOCK; + DRM_LOCK; if (idx < 0 || idx >= dev->map_count) { - DRM_OS_UNLOCK; - return DRM_OS_ERR(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; - return DRM_OS_ERR(EINVAL); + DRM_UNLOCK; + return DRM_ERR(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) { @@ -229,47 +166,29 @@ int DRM(getmap)( DRM_OS_IOCTL ) } i++; } -#endif /* __FreeBSD__ */ - DRM_OS_UNLOCK; + DRM_UNLOCK; -#ifdef __FreeBSD__ if (!list) return EINVAL; -#endif /* __FreeBSD__ */ - DRM_OS_KRNTOUSR( (drm_map_t *)data, map, sizeof(map) ); + DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) ); return 0; } -int DRM(getclient)( DRM_OS_IOCTL ) +int DRM(getclient)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_client_t client; drm_file_t *pt; int idx; int i = 0; - DRM_OS_KRNFROMUSR( client, (drm_client_t *)data, sizeof(client) ); + DRM_COPY_FROM_USER_IOCTL( 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; - return DRM_OS_ERR(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__ + DRM_LOCK; TAILQ_FOREACH(pt, &dev->files, link) { if (i==idx) { @@ -278,30 +197,29 @@ int DRM(getclient)( DRM_OS_IOCTL ) client.uid = pt->uid; client.magic = pt->magic; client.iocs = pt->ioctl_count; - DRM_OS_UNLOCK; + DRM_UNLOCK; *(drm_client_t *)data = client; return 0; } i++; } -#endif /* __FreeBSD__ */ - DRM_OS_UNLOCK; + DRM_UNLOCK; - DRM_OS_KRNTOUSR( (drm_client_t *)data, client, sizeof(client) ); + DRM_COPY_TO_USER_IOCTL( (drm_client_t *)data, client, sizeof(client) ); return 0; } -int DRM(getstats)( DRM_OS_IOCTL ) +int DRM(getstats)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_stats_t stats; int i; memset(&stats, 0, sizeof(stats)); - DRM_OS_LOCK; + DRM_LOCK; for (i = 0; i < dev->counters; i++) { if (dev->types[i] == _DRM_STAT_LOCK) @@ -315,9 +233,9 @@ int DRM(getstats)( DRM_OS_IOCTL ) stats.count = dev->counters; - DRM_OS_UNLOCK; + DRM_UNLOCK; - DRM_OS_KRNTOUSR( (drm_stats_t *)data, stats, sizeof(stats) ); + DRM_COPY_TO_USER_IOCTL( (drm_stats_t *)data, stats, sizeof(stats) ); return 0; } diff --git a/sys/dev/drm/drm_lists.h b/sys/dev/drm/drm_lists.h index bc26687..b8f6fed 100644 --- a/sys/dev/drm/drm_lists.h +++ b/sys/dev/drm/drm_lists.h @@ -31,7 +31,6 @@ * $FreeBSD$ */ -#define __NO_VERSION__ #include "dev/drm/drmP.h" #if __HAVE_DMA_WAITLIST @@ -39,26 +38,28 @@ int DRM(waitlist_create)(drm_waitlist_t *bl, int count) { if (bl->count) - return DRM_OS_ERR(EINVAL); + return DRM_ERR( EINVAL ); bl->bufs = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs), DRM_MEM_BUFLISTS); - if(!bl->bufs) return DRM_OS_ERR(ENOMEM); + if(!bl->bufs) return DRM_ERR(ENOMEM); + + bzero(bl->bufs, sizeof(*bl->bufs)); 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" ); + DRM_SPININIT( bl->write_lock, "writelock" ); + DRM_SPININIT( bl->read_lock, "readlock" ); return 0; } int DRM(waitlist_destroy)(drm_waitlist_t *bl) { if (bl->rp != bl->wp) - return DRM_OS_ERR(EINVAL); + return DRM_ERR( EINVAL ); if (bl->bufs) DRM(free)(bl->bufs, (bl->count + 2) * sizeof(*bl->bufs), DRM_MEM_BUFLISTS); @@ -67,50 +68,32 @@ int DRM(waitlist_destroy)(drm_waitlist_t *bl) bl->rp = NULL; bl->wp = NULL; bl->end = NULL; + DRM_SPINUNINIT( bl->write_lock ); + DRM_SPINUNINIT( bl->read_lock ); 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); - return DRM_OS_ERR(EINVAL); + return DRM_ERR( 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); + DRM_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__ */ + DRM_SPINUNLOCK(&bl->write_lock); return 0; } @@ -118,36 +101,19 @@ int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf) 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); + DRM_SPINLOCK(&bl->read_lock); s = spldrm(); buf = *bl->rp; if (bl->rp == bl->wp) { splx(s); - DRM_OS_SPINUNLOCK(&bl->read_lock); + DRM_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__ */ + DRM_SPINUNLOCK(&bl->read_lock); return buf; } @@ -161,17 +127,12 @@ 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" ); + DRM_SPININIT( bl->lock, "freelistlock" ); ++bl->initialized; return 0; } @@ -180,6 +141,7 @@ int DRM(freelist_destroy)(drm_freelist_t *bl) { atomic_set(&bl->count, 0); bl->next = NULL; + DRM_SPINUNINIT( bl->lock ); return 0; } @@ -198,20 +160,15 @@ int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf) } 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 ); + DRM_SPINLOCK( &bl->lock ); buf->next = bl->next; bl->next = buf; - DRM_OS_SPINUNLOCK( &bl->lock ); + DRM_SPINUNLOCK( &bl->lock ); atomic_inc(&bl->count); if (atomic_read(&bl->count) > dma->buf_count) { @@ -223,7 +180,7 @@ int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf) /* 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); + DRM_WAKEUP_INT((void *)&bl->waiting); } return 0; } @@ -235,14 +192,14 @@ static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl) if (!bl) return NULL; /* Get buffer */ - DRM_OS_SPINLOCK(&bl->lock); + DRM_SPINLOCK(&bl->lock); if (!bl->next) { - DRM_OS_SPINUNLOCK(&bl->lock); + DRM_SPINUNLOCK(&bl->lock); return NULL; } buf = bl->next; bl->next = bl->next->next; - DRM_OS_SPINUNLOCK(&bl->lock); + DRM_SPINUNLOCK(&bl->lock); atomic_dec(&bl->count); buf->next = NULL; @@ -258,12 +215,7 @@ static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl) 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; @@ -272,28 +224,14 @@ drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block) 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, + error = tsleep((void *)&bl->waiting, PZERO|PCATCH, "drmfg", 0); if (error) break; } -#endif /* __FreeBSD__ */ } return buf; } diff --git a/sys/dev/drm/drm_lock.h b/sys/dev/drm/drm_lock.h index e3b1f5e..de07146 100644 --- a/sys/dev/drm/drm_lock.h +++ b/sys/dev/drm/drm_lock.h @@ -31,16 +31,15 @@ * $FreeBSD$ */ -#define __NO_VERSION__ #include "dev/drm/drmP.h" -int DRM(block)( DRM_OS_IOCTL ) +int DRM(block)( DRM_IOCTL_ARGS ) { DRM_DEBUG("\n"); return 0; } -int DRM(unblock)( DRM_OS_IOCTL ) +int DRM(unblock)( DRM_IOCTL_ARGS ) { DRM_DEBUG("\n"); return 0; @@ -49,26 +48,13 @@ int DRM(unblock)( DRM_OS_IOCTL ) 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__ */ + } while (!atomic_cmpset_int(lock, old, new)); + if (_DRM_LOCKING_CONTEXT(old) == context) { if (old & _DRM_LOCK_HELD) { if (context != DRM_KERNEL_CONTEXT) { @@ -91,25 +77,13 @@ 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__ */ + } while (!atomic_cmpset_int(lock, old, new)); + return 1; } @@ -117,26 +91,14 @@ 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__ */ + } while (!atomic_cmpset_int(lock, old, new)); + if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) { DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n", context, @@ -144,18 +106,13 @@ int DRM(lock_free)(drm_device_t *dev, pid); return 1; } - DRM_OS_WAKEUP_INT(&dev->lock.lock_queue); + DRM_WAKEUP_INT((void *)&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]; @@ -164,30 +121,11 @@ static int DRM(flush_queue)(drm_device_t *dev, int context) 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); + error = tsleep((void *)&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); @@ -206,7 +144,7 @@ static int DRM(flush_unblock_queue)(drm_device_t *dev, int context) 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); + DRM_WAKEUP_INT((void *)&q->write_queue); } } atomic_dec(&q->use_count); @@ -253,15 +191,15 @@ int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags) return ret; } -int DRM(finish)( DRM_OS_IOCTL ) +int DRM(finish)( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; int ret = 0; drm_lock_t lock; DRM_DEBUG("\n"); - DRM_OS_KRNFROMUSR( lock, (drm_lock_t *)data, sizeof(lock) ); + DRM_COPY_FROM_USER_IOCTL( 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); @@ -284,13 +222,6 @@ 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) @@ -301,14 +232,8 @@ int DRM(notifier)(void *priv) 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__ */ + } while (!atomic_cmpset_int(&s->lock->lock, old, new)); + return 0; } diff --git a/sys/dev/drm/drm_memory.h b/sys/dev/drm/drm_memory.h index 81fa561..5515524 100644 --- a/sys/dev/drm/drm_memory.h +++ b/sys/dev/drm/drm_memory.h @@ -31,28 +31,16 @@ * $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 +#if defined(__FreeBSD__) || defined(__NetBSD__) #define malloctype DRM(M_DRM) -/* The macros confliced in the MALLOC_DEFINE */ +/* The macros conflicted in the MALLOC_DEFINE */ MALLOC_DEFINE(malloctype, "drm", "DRM Data Structures"); #undef malloctype -#endif /* __FreeBSD__ */ +#endif typedef struct drm_mem_stats { const char *name; @@ -63,12 +51,7 @@ typedef struct drm_mem_stats { 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 DRM_SPINTYPE DRM(mem_lock); static unsigned long DRM(ram_available) = 0; /* In pages */ static unsigned long DRM(ram_used) = 0; static drm_mem_stats_t DRM(mem_stats)[] = { @@ -99,13 +82,12 @@ static drm_mem_stats_t DRM(mem_stats)[] = { 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__ */ +#ifdef __NetBSD__ + malloc_type_attach(DRM(M_DRM)); +#endif + + DRM_SPININIT(DRM(mem_lock), "drm memory"); for (mem = DRM(mem_stats); mem->name; ++mem) { mem->succeed_count = 0; @@ -115,18 +97,18 @@ void DRM(mem_init)(void) 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; } +void DRM(mem_uninit)(void) +{ + DRM_SPINUNINIT(DRM(mem_lock)); +} + #ifdef __FreeBSD__ -static int +/* drm_mem_info is called whenever a process reads /dev/drm/mem. */ +static int DRM(_mem_info)(drm_mem_stats_t *stats, struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req) { @@ -169,9 +151,9 @@ int DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS if (stats == NULL) return ENOMEM; - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_SPINLOCK(&DRM(mem_lock)); bcopy(DRM(mem_stats), stats, sizeof(DRM(mem_stats))); - DRM_OS_SPINUNLOCK(&DRM(mem_lock)); + DRM_SPINUNLOCK(&DRM(mem_lock)); ret = DRM(_mem_info)(stats, oidp, arg1, arg2, req); @@ -189,21 +171,16 @@ void *DRM(alloc)(size_t size, int area) 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_SPINLOCK(&DRM(mem_lock)); ++DRM(mem_stats)[area].fail_count; - DRM_OS_SPINUNLOCK(&DRM(mem_lock)); + DRM_SPINUNLOCK(&DRM(mem_lock)); return NULL; } - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_SPINLOCK(&DRM(mem_lock)); ++DRM(mem_stats)[area].succeed_count; DRM(mem_stats)[area].bytes_allocated += size; - DRM_OS_SPINUNLOCK(&DRM(mem_lock)); + DRM_SPINUNLOCK(&DRM(mem_lock)); return pt; } @@ -244,119 +221,58 @@ 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)); + if (!pt) + DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n"); + else + free(pt, DRM(M_DRM)); + DRM_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)); + DRM_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) +void *DRM(ioremap)( drm_device_t *dev, drm_local_map_t *map ) { -#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); + void *pt; -#ifdef __linux__ - /* Reserve */ - for (addr = address, sz = bytes; - sz > 0; - addr += PAGE_SIZE, sz -= PAGE_SIZE) { - mem_map_reserve(virt_to_page(addr)); + if (!map->size) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Mapping 0 bytes at 0x%08lx\n", map->offset); + return NULL; } -#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; +#ifdef __NetBSD__ + map->iot = dev->pa.pa_memt; +#endif - 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); + if (!(pt = pmap_mapdev(map->offset, map->size))) { +#elif defined(__NetBSD__) + if (bus_space_map(map->iot, map->offset, map->size, + BUS_SPACE_MAP_LINEAR, &map->ioh)) { +#endif + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return NULL; } +#ifdef __NetBSD__ + pt = bus_space_vaddr(map->iot, map->ioh); +#endif + DRM_SPINLOCK(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; + DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += map->size; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return pt; } -void *DRM(ioremap)(unsigned long offset, unsigned long size) +/* unused so far */ +#if 0 +void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size) { void *pt; @@ -366,45 +282,41 @@ void *DRM(ioremap)(unsigned long offset, unsigned long size) 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)); + /* FIXME FOR BSD */ + if (!(pt = ioremap_nocache(offset, size))) { + DRM_SPINLOCK(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; - DRM_OS_SPINUNLOCK(&DRM(mem_lock)); + DRM_SPINUNLOCK(&DRM(mem_lock)); return NULL; } - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_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)); + DRM_SPINUNLOCK(&DRM(mem_lock)); return pt; } +#endif -void DRM(ioremapfree)(void *pt, unsigned long size) +void DRM(ioremapfree)(drm_local_map_t *map) { int alloc_count; int free_count; - if (!pt) + if (map->handle == NULL) 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__ */ + pmap_unmapdev((vm_offset_t) map->handle, map->size); +#elif defined(__NetBSD__) + bus_space_unmap(map->iot, map->ioh, map->size); +#endif - DRM_OS_SPINLOCK(&DRM(mem_lock)); - DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size; + DRM_SPINLOCK(&DRM(mem_lock)); + DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += map->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)); + DRM_SPINUNLOCK(&DRM(mem_lock)); if (free_count > alloc_count) { DRM_MEM_ERROR(DRM_MEM_MAPPINGS, "Excess frees: %d frees, %d allocs\n", @@ -423,16 +335,16 @@ agp_memory *DRM(alloc_agp)(int pages, u32 type) } if ((handle = DRM(agp_allocate_memory)(pages, type))) { - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_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)); + DRM_SPINUNLOCK(&DRM(mem_lock)); return handle; } - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_SPINLOCK(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count; - DRM_OS_SPINUNLOCK(&DRM(mem_lock)); + DRM_SPINUNLOCK(&DRM(mem_lock)); return NULL; } @@ -444,16 +356,16 @@ int DRM(free_agp)(agp_memory *handle, int pages) if (!handle) { DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Attempt to free NULL AGP handle\n"); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if (DRM(agp_free_memory)(handle)) { - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_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)); + DRM_SPINUNLOCK(&DRM(mem_lock)); if (free_count > alloc_count) { DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Excess frees: %d frees, %d allocs\n", @@ -461,90 +373,72 @@ int DRM(free_agp)(agp_memory *handle, int pages) } return 0; } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } int DRM(bind_agp)(agp_memory *handle, unsigned int start) { int retcode; -#ifdef __FreeBSD__ - device_t dev = agp_find_device(); + device_t dev = DRM_AGP_FIND_DEVICE(); struct agp_memory_info info; if (!dev) - return DRM_OS_ERR(EINVAL); -#endif /* __FreeBSD__ */ + return EINVAL; if (!handle) { DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, "Attempt to bind NULL AGP handle\n"); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if (!(retcode = DRM(agp_bind_memory)(handle, start))) { - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_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)); - return 0; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return DRM_ERR(0); } - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_SPINLOCK(&DRM(mem_lock)); ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count; - DRM_OS_SPINUNLOCK(&DRM(mem_lock)); - return retcode; + DRM_SPINUNLOCK(&DRM(mem_lock)); + return DRM_ERR(retcode); } int DRM(unbind_agp)(agp_memory *handle) { int alloc_count; int free_count; - int retcode = DRM_OS_ERR(EINVAL); -#ifdef __FreeBSD__ - device_t dev = agp_find_device(); + int retcode = EINVAL; + device_t dev = DRM_AGP_FIND_DEVICE(); struct agp_memory_info info; if (!dev) - return DRM_OS_ERR(EINVAL); -#endif /* __FreeBSD__ */ + return EINVAL; if (!handle) { DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, "Attempt to unbind NULL AGP handle\n"); - return retcode; + return DRM_ERR(retcode); } -#ifdef __FreeBSD__ agp_memory_info(dev, handle, &info); -#endif /* __FreeBSD__ */ if ((retcode = DRM(agp_unbind_memory)(handle))) - return retcode; + return DRM_ERR(retcode); - DRM_OS_SPINLOCK(&DRM(mem_lock)); + DRM_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)); + DRM_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); } - return retcode; + return DRM_ERR(retcode); } #endif diff --git a/sys/dev/drm/drm_os_freebsd.h b/sys/dev/drm/drm_os_freebsd.h index e7c5901..16952fd 100644 --- a/sys/dev/drm/drm_os_freebsd.h +++ b/sys/dev/drm/drm_os_freebsd.h @@ -1,10 +1,8 @@ /* * $FreeBSD$ */ - #include <sys/param.h> #include <sys/queue.h> -#include <sys/lockmgr.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/module.h> @@ -17,11 +15,26 @@ #include <sys/uio.h> #include <sys/filio.h> #include <sys/sysctl.h> +#include <sys/bus.h> +#include <sys/signalvar.h> +#include <sys/poll.h> #include <vm/vm.h> #include <vm/pmap.h> +#include <vm/vm_extern.h> +#include <vm/vm_map.h> +#include <vm/vm_param.h> +#include <machine/param.h> #include <machine/pmap.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/mman.h> +#include <sys/rman.h> +#include <sys/memrange.h> +#include <pci/pcivar.h> #if __FreeBSD_version >= 500000 #include <sys/selinfo.h> +#else +#include <sys/select.h> #endif #include <sys/bus.h> #if __FreeBSD_version >= 400005 @@ -35,14 +48,14 @@ #define __REALLY_HAVE_AGP __HAVE_AGP #endif -#define __REALLY_HAVE_MTRR 0 -#define __REALLY_HAVE_SG 0 +#define __REALLY_HAVE_MTRR (__HAVE_MTRR) +#define __REALLY_HAVE_SG (__HAVE_SG) #if __REALLY_HAVE_AGP #include <pci/agpvar.h> +#include <sys/agpio.h> #endif -/* Allow setting of debug code enabling from kernel config file */ #include <opt_drm.h> #if DRM_DEBUG #undef DRM_DEBUG_CODE @@ -50,50 +63,73 @@ #endif #undef DRM_DEBUG +#if DRM_LINUX +#include <sys/file.h> +#include <sys/proc.h> +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#endif + #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 +#define CDEV_MAJOR 145 #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 +#define DRM_CURPROC curthread +#define DRM_STRUCTPROC struct thread +#define DRM_SPINTYPE struct mtx +#define DRM_SPININIT(l,name) mtx_init(&l, name, NULL, MTX_DEF) +#define DRM_SPINUNINIT(l) mtx_destroy(&l) +#define DRM_SPINLOCK(l) mtx_lock(l) +#define DRM_SPINUNLOCK(u) mtx_unlock(u); +#define DRM_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 +#define DRM_CURPROC curproc +#define DRM_STRUCTPROC struct proc +#define DRM_SPINTYPE struct simplelock +#define DRM_SPININIT(l,name) simple_lock_init(&l) +#define DRM_SPINUNINIT(l) +#define DRM_SPINLOCK(l) simple_lock(l) +#define DRM_SPINUNLOCK(u) simple_unlock(u); +#define DRM_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 IOCTL_ARGS_PASS kdev, cmd, data, flags, 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 \ +#define DRM_IOCTL_ARGS dev_t kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p +#define DRM_LOCK lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, DRM_CURPROC) +#define DRM_UNLOCK lockmgr(&dev->dev_lock, LK_RELEASE, 0, DRM_CURPROC) +#define DRM_SUSER(p) suser(p) +#define DRM_TASKQUEUE_ARGS void *arg, int pending +#define DRM_IRQ_ARGS void *arg +#define DRM_DEVICE drm_device_t *dev = kdev->si_drv1 +#define DRM_MALLOC(size) malloc( size, DRM(M_DRM), M_NOWAIT ) +#define DRM_FREE(pt,size) free( pt, DRM(M_DRM) ) +#define DRM_VTOPHYS(addr) vtophys(addr) + +/* Read/write from bus space, with byteswapping to le if necessary */ +#define DRM_READ8(map, offset) *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset)) +#define DRM_READ32(map, offset) *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) +#define DRM_WRITE8(map, offset, val) *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset)) = val +#define DRM_WRITE32(map, offset, val) *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) = val +/* +#define DRM_READ8(map, offset) bus_space_read_1( (map)->iot, (map)->ioh, (offset) ) +#define DRM_READ32(map, offset) bus_space_read_4( (map)->iot, (map)->ioh, (offset) ) +#define DRM_WRITE8(map, offset, val) bus_space_write_1( (map)->iot, (map)->ioh, (offset), (val) ) +#define DRM_WRITE32(map, offset, val) bus_space_write_4( (map)->iot, (map)->ioh, (offset), (val) ) +*/ +#define DRM_AGP_FIND_DEVICE() agp_find_device() +#define DRM_ERR(v) v + +#define DRM_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 ) \ +#define DRM_UDELAY( udelay ) \ do { \ struct timeval tv1, tv2; \ microtime(&tv1); \ @@ -103,38 +139,65 @@ do { \ while (((tv2.tv_sec-tv1.tv_sec)*1000000 + tv2.tv_usec - tv1.tv_usec) < udelay ); \ } while (0) -#define DRM_OS_ERR(v) v +#define DRM_GETSAREA() \ +do { \ + drm_map_list_entry_t *listentry; \ + TAILQ_FOREACH(listentry, dev->maplist, link) { \ + drm_local_map_t *map = listentry->map; \ + if (map->type == _DRM_SHM && \ + map->flags & _DRM_CONTAINS_LOCK) { \ + dev_priv->sarea = map; \ + break; \ + } \ + } \ +} while (0) +#define DRM_HZ hz -#define DRM_OS_KRNTOUSR( user, kern, size) \ +#define DRM_WAIT_ON( ret, queue, timeout, condition ) \ +while (!condition) { \ + ret = tsleep( &(queue), PZERO | PCATCH, "drmwtq", (timeout) ); \ + if ( ret ) \ + return ret; \ +} + +#define DRM_WAKEUP( queue ) wakeup( queue ) +#define DRM_WAKEUP_INT( queue ) wakeup( queue ) +#define DRM_INIT_WAITQUEUE( queue ) do {} while (0) + +#define DRM_COPY_TO_USER_IOCTL(user, kern, size) \ if ( IOCPARM_LEN(cmd) != size) \ return EINVAL; \ *user = kern; -#define DRM_OS_KRNFROMUSR(kern, user, size) \ +#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \ if ( IOCPARM_LEN(cmd) != size) \ return EINVAL; \ kern = *user; -#define DRM_OS_COPYTOUSR(user, kern, size) \ +#define DRM_COPY_TO_USER(user, kern, size) \ copyout(kern, user, size) -#define DRM_OS_COPYFROMUSR(kern, user, size) \ +#define DRM_COPY_FROM_USER(kern, user, size) \ copyin(user, kern, size) - -#define DRM_OS_READMEMORYBARRIER \ -{ \ - int xchangeDummy; \ - DRM_DEBUG("%s\n", __func__); \ - __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) +/* Macros for userspace access with checking readability once */ +/* FIXME: can't find equivalent functionality for nocheck yet. + * It'll be slower than linux, but should be correct. + */ +#define DRM_VERIFYAREA_READ( uaddr, size ) \ + (!useracc((caddr_t)uaddr, size, VM_PROT_READ)) +#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \ + copyin(arg2, arg1, arg3) +#define DRM_GET_USER_UNCHECKED(val, uaddr) \ + ((val) = fuword(uaddr), 0) + +#define DRM_WRITEMEMORYBARRIER( map ) \ + bus_space_barrier((map)->iot, (map)->ioh, 0, (map)->size, 0); +#define DRM_READMEMORYBARRIER( map ) \ + bus_space_barrier((map)->iot, (map)->ioh, 0, (map)->size, BUS_SPACE_BARRIER_READ); + +#define PAGE_ALIGN(addr) round_page(addr) + +#ifndef M_WAITOK /* M_WAITOK (=0) name removed in -current */ +#define M_WAITOK 0 +#endif #define malloctype DRM(M_DRM) /* The macros confliced in the MALLOC_DEFINE */ @@ -149,7 +212,10 @@ typedef struct drm_chipinfo char *name; } drm_chipinfo_t; -typedef unsigned long atomic_t; +#define cpu_to_le32(x) (x) /* FIXME */ + +typedef u_int32_t dma_addr_t; +typedef u_int32_t atomic_t; typedef u_int32_t cycles_t; typedef u_int32_t spinlock_t; typedef u_int32_t u32; @@ -157,50 +223,67 @@ 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) +#define atomic_inc(p) atomic_add_int(p, 1) +#define atomic_dec(p) atomic_subtract_int(p, 1) +#define atomic_add(n, p) atomic_add_int(p, n) +#define atomic_sub(n, p) atomic_subtract_int(p, n) /* Fake this */ -static __inline unsigned int -test_and_set_bit(int b, volatile unsigned long *p) + +#if __FreeBSD_version < 500000 +/* The extra atomic functions from 5.0 haven't been merged to 4.x */ +static __inline int +atomic_cmpset_int(volatile int *dst, int old, int new) +{ + int s = splhigh(); + if (*dst==old) { + *dst = new; + splx(s); + return 1; + } + splx(s); + return 0; +} +#endif + +static __inline atomic_t +test_and_set_bit(int b, volatile void *p) { int s = splhigh(); unsigned int m = 1<<b; - unsigned int r = *p & m; - *p |= m; + unsigned int r = *(volatile int *)p & m; + *(volatile int *)p |= m; splx(s); return r; } static __inline void -clear_bit(int b, volatile unsigned long *p) +clear_bit(int b, volatile void *p) { - atomic_clear_long(p + (b >> 5), 1 << (b & 0x1f)); + atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); } static __inline void -set_bit(int b, volatile unsigned long *p) +set_bit(int b, volatile void *p) { - atomic_set_long(p + (b >> 5), 1 << (b & 0x1f)); + atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); } static __inline int -test_bit(int b, volatile unsigned long *p) +test_bit(int b, volatile void *p) { - return p[b >> 5] & (1 << (b & 0x1f)); + return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f)); } static __inline int -find_first_zero_bit(volatile unsigned long *p, int max) +find_first_zero_bit(volatile void *p, int max) { int b; for (b = 0; b < max; b += 32) { - if (p[b >> 5] != ~0) { + if (((volatile int *)p)[b >> 5] != ~0) { for (;;) { - if ((p[b >> 5] & (1 << (b & 0x1f))) == 0) + if ((((volatile int *)p)[b >> 5] & (1 << (b & 0x1f))) == 0) return b; b++; } @@ -224,40 +307,24 @@ find_first_zero_bit(volatile unsigned long *p, int max) #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 wait_queue_head_t atomic_t #define agp_memory void #define jiffies ticks /* Macros to make printf easier */ #define DRM_ERROR(fmt, arg...) \ - printf("error: [" DRM_NAME ":%s] *ERROR* " fmt , \ - __func__, ##arg) + printf("error: " "[" DRM_NAME ":%s] *ERROR* " fmt , __func__ , ## arg) #define DRM_MEM_ERROR(area, fmt, arg...) \ - printf("error: [" DRM_NAME ":%s:%s] *ERROR* " fmt , \ - __func__, DRM(mem_stats)[area].name , ##arg) -#define DRM_INFO(fmt, arg...) printf("info: " "[" DRM_NAME "] " fmt , ##arg) + printf("error: " "[" DRM_NAME ":%s:%s] *ERROR* " fmt , \ + __func__, 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 ":%s] " fmt , \ - __func__, ##arg); \ +#define DRM_DEBUG(fmt, arg...) \ + do { \ + if (DRM(flags) & DRM_FLAG_DEBUG) \ + printf("[" DRM_NAME ":%s] " fmt , __func__ , ## arg); \ } while (0) #else #define DRM_DEBUG(fmt, arg...) do { } while (0) @@ -297,6 +364,9 @@ find_first_zero_bit(volatile unsigned long *p, int max) /* 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); @@ -304,13 +374,85 @@ 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); + DRM_STRUCTPROC *p, drm_device_t *dev); extern drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, - DRM_OS_STRUCTPROC *p); + DRM_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 +extern d_ioctl_t DRM(control); +#endif +#if __HAVE_VBL_IRQ +extern d_ioctl_t DRM(wait_vblank); +#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_sarea.h b/sys/dev/drm/drm_sarea.h new file mode 100644 index 0000000..f3dc820 --- /dev/null +++ b/sys/dev/drm/drm_sarea.h @@ -0,0 +1,59 @@ +/* sarea.h -- SAREA definitions -*- linux-c -*- + * + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Michel Dänzer <michel@daenzer.net> + * + * $FreeBSD$ + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#define SAREA_MAX_DRAWABLES 256 + +typedef struct _drm_sarea_drawable_t { + unsigned int stamp; + unsigned int flags; +} drm_sarea_drawable_t; + +typedef struct _dri_sarea_frame_t { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +} drm_sarea_frame_t; + +typedef struct _drm_sarea_t { + /* first thing is always the drm locking structure */ + drm_hw_lock_t lock; + /* NOT_DONE: Use readers/writer lock for drawable_lock */ + drm_hw_lock_t drawable_lock; + drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; + drm_sarea_frame_t frame; + drm_context_t dummy_context; +} drm_sarea_t; + +#endif /* _DRM_SAREA_H_ */ diff --git a/sys/dev/drm/drm_scatter.h b/sys/dev/drm/drm_scatter.h index d7f090f..244c9ff 100644 --- a/sys/dev/drm/drm_scatter.h +++ b/sys/dev/drm/drm_scatter.h @@ -29,207 +29,106 @@ * $FreeBSD$ */ -#define __NO_VERSION__ -#include <linux/config.h> -#include <linux/vmalloc.h> #include "dev/drm/drmP.h" #define DEBUG_SCATTER 0 +#if __REALLY_HAVE_SG + 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 ); + free( entry->virtual, DRM(M_DRM) ); 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 ) +int DRM(sg_alloc)( DRM_IOCTL_ARGS ) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; + DRM_DEVICE; drm_scatter_gather_t request; drm_sg_mem_t *entry; - unsigned long pages, i, j; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; + unsigned long pages; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( dev->sg ) - return DRM_OS_ERR(EINVAL); + return EINVAL; - if ( copy_from_user( &request, - (drm_scatter_gather_t *)arg, - sizeof(request) ) ) - return DRM_OS_ERR(EFAULT); + DRM_COPY_FROM_USER_IOCTL(request, (drm_scatter_gather_t *)data, + sizeof(request) ); entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS ); if ( !entry ) - return DRM_OS_ERR(ENOMEM); + return ENOMEM; - memset( entry, 0, sizeof(*entry) ); + bzero( entry, sizeof(*entry) ); - pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; + pages = round_page(request.size) / 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 DRM_OS_ERR(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 DRM_OS_ERR(ENOMEM); + return ENOMEM; } - memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) ); + bzero( (void *)entry->busaddr, pages * sizeof(*entry->busaddr) ); - entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); + entry->virtual = malloc( pages << PAGE_SHIFT, DRM(M_DRM), M_WAITOK ); 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 DRM_OS_ERR(ENOMEM); + 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 ); + bzero( entry->virtual, 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 DRM_OS_ERR(EFAULT); - } + DRM_COPY_TO_USER_IOCTL( (drm_scatter_gather_t *)data, + request, + sizeof(request) ); 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 DRM_OS_ERR(ENOMEM); + return ENOMEM; } -int DRM(sg_free)( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) +int DRM(sg_free)( DRM_IOCTL_ARGS ) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; + DRM_DEVICE; drm_scatter_gather_t request; drm_sg_mem_t *entry; - if ( copy_from_user( &request, - (drm_scatter_gather_t *)arg, - sizeof(request) ) ) - return DRM_OS_ERR(EFAULT); + DRM_COPY_FROM_USER_IOCTL( request, (drm_scatter_gather_t *)data, + sizeof(request) ); entry = dev->sg; dev->sg = NULL; if ( !entry || entry->handle != request.handle ) - return DRM_OS_ERR(EINVAL); + return EINVAL; DRM_DEBUG( "sg free virtual = %p\n", entry->virtual ); @@ -237,3 +136,16 @@ int DRM(sg_free)( struct inode *inode, struct file *filp, return 0; } + +#else /* __REALLY_HAVE_SG */ + +int DRM(sg_alloc)( DRM_IOCTL_ARGS ) +{ + return DRM_ERR(EINVAL); +} +int DRM(sg_free)( DRM_IOCTL_ARGS ) +{ + return DRM_ERR(EINVAL); +} + +#endif diff --git a/sys/dev/drm/drm_sysctl.h b/sys/dev/drm/drm_sysctl.h index 776b21f..b2522e6 100644 --- a/sys/dev/drm/drm_sysctl.h +++ b/sys/dev/drm/drm_sysctl.h @@ -1,9 +1,9 @@ /* * $FreeBSD$ */ - -#include "dev/drm/drm.h" -#include "dev/drm/drmP.h" + +#ifdef __FreeBSD__ + #include <sys/sysctl.h> static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS; @@ -125,7 +125,7 @@ static int DRM(name_info)DRM_SYSCTL_HANDLER_ARGS static int DRM(_vm_info)DRM_SYSCTL_HANDLER_ARGS { drm_device_t *dev = arg1; - drm_map_t *map; + drm_local_map_t *map; drm_map_list_entry_t *listentry; const char *types[] = { "FB", "REG", "SHM" }; const char *type; @@ -168,9 +168,9 @@ static int DRM(vm_info)DRM_SYSCTL_HANDLER_ARGS drm_device_t *dev = arg1; int ret; - DRM_OS_LOCK; + DRM_LOCK; ret = DRM(_vm_info)(oidp, arg1, arg2, req); - DRM_OS_UNLOCK; + DRM_UNLOCK; return ret; } @@ -191,8 +191,8 @@ static int DRM(_queues_info)DRM_SYSCTL_HANDLER_ARGS 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", + "%5d/0x%03x %5d %5d" + " %5d/%c%c/%c%c%c %5d %10d %10d %10d\n", i, q->flags, atomic_read(&q->use_count), @@ -203,7 +203,7 @@ static int DRM(_queues_info)DRM_SYSCTL_HANDLER_ARGS q->read_queue ? 'r':'-', q->write_queue ? 'w':'-', q->flush_queue ? 'f':'-', - DRM_BUFCOUNT(&q->waitlist), + (int)DRM_BUFCOUNT(&q->waitlist), atomic_read(&q->total_flushed), atomic_read(&q->total_queued), atomic_read(&q->total_locks)); @@ -219,9 +219,9 @@ static int DRM(queues_info) DRM_SYSCTL_HANDLER_ARGS drm_device_t *dev = arg1; int ret; - DRM_OS_LOCK; + DRM_LOCK; ret = DRM(_queues_info)(oidp, arg1, arg2, req); - DRM_OS_UNLOCK; + DRM_UNLOCK; return ret; } @@ -240,7 +240,7 @@ static int DRM(_bufs_info) DRM_SYSCTL_HANDLER_ARGS 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", + DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n", i, dma->bufs[i].buf_size, dma->bufs[i].buf_count, @@ -269,9 +269,9 @@ static int DRM(bufs_info) DRM_SYSCTL_HANDLER_ARGS drm_device_t *dev = arg1; int ret; - DRM_OS_LOCK; + DRM_LOCK; ret = DRM(_bufs_info)(oidp, arg1, arg2, req); - DRM_OS_UNLOCK; + DRM_UNLOCK; return ret; } @@ -303,9 +303,9 @@ static int DRM(clients_info)DRM_SYSCTL_HANDLER_ARGS drm_device_t *dev = arg1; int ret; - DRM_OS_LOCK; + DRM_LOCK; ret = DRM(_clients_info)(oidp, arg1, arg2, req); - DRM_OS_UNLOCK; + DRM_UNLOCK; return ret; } @@ -388,9 +388,9 @@ static int DRM(vma_info)DRM_SYSCTL_HANDLER_ARGS drm_device_t *dev = arg1; int ret; - DRM_OS_LOCK; + DRM_LOCK; ret = DRM(_vma_info)(oidp, arg1, arg2, req); - DRM_OS_UNLOCK; + DRM_UNLOCK; return ret; } #endif @@ -517,9 +517,22 @@ static int DRM(histo_info)DRM_SYSCTL_HANDLER_ARGS drm_device_t *dev = arg1; int ret; - DRM_OS_LOCK; + DRM_LOCK; ret = _drm_histo_info(oidp, arg1, arg2, req); - DRM_OS_UNLOCK; + DRM_UNLOCK; return ret; } #endif + +#elif defined(__NetBSD__) +/* stub it out for now, sysctl is only for debugging */ +int DRM(sysctl_init)(drm_device_t *dev) +{ + return 0; +} + +int DRM(sysctl_cleanup)(drm_device_t *dev) +{ + return 0; +} +#endif diff --git a/sys/dev/drm/drm_vm.h b/sys/dev/drm/drm_vm.h index 705ca48..a2ea15d 100644 --- a/sys/dev/drm/drm_vm.h +++ b/sys/dev/drm/drm_vm.h @@ -2,13 +2,16 @@ * $FreeBSD$ */ -#include <vm/vm.h> -#include <vm/pmap.h> - -static int DRM(dma_mmap)(dev_t kdev, vm_offset_t offset, vm_offset_t *paddr, +#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 +static int DRM(dma_mmap)(dev_t kdev, vm_offset_t offset, vm_offset_t *paddr, int prot) +#elif defined(__FreeBSD__) +static int DRM(dma_mmap)(dev_t kdev, vm_offset_t offset, int prot) +#elif defined(__NetBSD__) +static paddr_t DRM(dma_mmap)(dev_t kdev, vm_offset_t offset, int prot) +#endif { - drm_device_t *dev = kdev->si_drv1; + DRM_DEVICE; drm_device_dma_t *dma = dev->dma; unsigned long physical; unsigned long page; @@ -19,33 +22,47 @@ static int DRM(dma_mmap)(dev_t kdev, vm_offset_t offset, vm_offset_t *paddr, page = offset >> PAGE_SHIFT; physical = dma->pagelist[page]; - DRM_DEBUG("0x%08x (page %lu) => 0x%08lx\n", offset, page, physical); + DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", (long)offset, page, physical); +#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 *paddr = physical; return 0; +#else + return atop(physical); +#endif } -int DRM(mmap)(dev_t kdev, vm_offset_t offset, vm_offset_t *paddr, int prot) +#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 +int DRM(mmap)(dev_t kdev, vm_offset_t offset, vm_offset_t *paddr, + int prot) +#elif defined(__FreeBSD__) +int DRM(mmap)(dev_t kdev, vm_offset_t offset, int prot) +#elif defined(__NetBSD__) +paddr_t DRM(mmap)(dev_t kdev, off_t offset, int prot) +#endif { - drm_device_t *dev = kdev->si_drv1; - drm_map_t *map = NULL; + DRM_DEVICE; + drm_local_map_t *map = NULL; drm_map_list_entry_t *listentry=NULL; - /*drm_file_t *priv;*/ + drm_file_t *priv; /* DRM_DEBUG("offset = 0x%x\n", offset);*/ - /*XXX Fixme */ - /*priv = DRM(find_file_by_proc)(dev, p); + priv = DRM(find_file_by_proc)(dev, DRM_CURPROC); if (!priv) { DRM_DEBUG("can't find authenticator\n"); return EINVAL; } - if (!priv->authenticated) return DRM_OS_ERR(EACCES);*/ + if (!priv->authenticated) return DRM_ERR(EACCES); if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) +#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 return DRM(dma_mmap)(kdev, offset, paddr, prot); +#else + return DRM(dma_mmap)(kdev, offset, prot); +#endif /* A sequential search of a linked list is fine here because: 1) there will only be @@ -65,7 +82,7 @@ int DRM(mmap)(dev_t kdev, vm_offset_t offset, vm_offset_t *paddr, int prot) DRM_DEBUG("can't find map\n"); return -1; } - if (((map->flags&_DRM_RESTRICTED) && suser(DRM_OS_CURPROC))) { + if (((map->flags&_DRM_RESTRICTED) && DRM_SUSER(DRM_CURPROC))) { DRM_DEBUG("restricted map\n"); return -1; } @@ -74,11 +91,20 @@ int DRM(mmap)(dev_t kdev, vm_offset_t offset, vm_offset_t *paddr, int prot) case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: case _DRM_AGP: +#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 *paddr = offset; return 0; +#else + return atop(offset); +#endif + case _DRM_SCATTER_GATHER: case _DRM_SHM: +#if defined(__FreeBSD__) && __FreeBSD_version >= 500102 *paddr = vtophys(offset); return 0; +#else + return atop(vtophys(offset)); +#endif default: return -1; /* This should never happen. */ } diff --git a/sys/dev/drm/gamma.h b/sys/dev/drm/gamma.h deleted file mode 100644 index 222fd11..0000000 --- a/sys/dev/drm/gamma.h +++ /dev/null @@ -1,95 +0,0 @@ -/* 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 deleted file mode 100644 index b550674..0000000 --- a/sys/dev/drm/gamma_dma.c +++ /dev/null @@ -1,647 +0,0 @@ -/* 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)) return DRM_OS_ERR(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); - return DRM_OS_ERR(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); - return DRM_OS_ERR(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); - return DRM_OS_ERR(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); - return DRM_OS_ERR(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 = DRM_OS_ERR(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 - - 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 */ - return DRM_OS_ERR(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); - return DRM_OS_ERR(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 DRM_OS_ERR(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 DRM_OS_ERR(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 = DRM_OS_ERR(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 = DRM_OS_ERR(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 = DRM_OS_ERR(EINVAL); - goto cleanup; - } - if (buf->waiting) { - DRM_ERROR("Sending waiting buffer:" - " buffer %d, offset %d\n", - d->send_indices[i], i); - retcode = DRM_OS_ERR(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 = DRM_OS_ERR(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); - 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 = DRM_OS_ERR(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); - } - } - 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); - return DRM_OS_ERR(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); - return DRM_OS_ERR(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 deleted file mode 100644 index b94d483..0000000 --- a/sys/dev/drm/gamma_drv.c +++ /dev/null @@ -1,124 +0,0 @@ -/* 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> -#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 deleted file mode 100644 index 255c361..0000000 --- a/sys/dev/drm/gamma_drv.h +++ /dev/null @@ -1,105 +0,0 @@ -/* 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", \ - __func__ ); \ - return DRM_OS_ERR(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 deleted file mode 100644 index 9f404c8..0000000 --- a/sys/dev/drm/i810_drm.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * $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; - -/* 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) - -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 index a469c09..2ee2c3f 100644 --- a/sys/dev/drm/mga.h +++ b/sys/dev/drm/mga.h @@ -43,6 +43,34 @@ #define __HAVE_MTRR 1 #define __HAVE_CTX_BITMAP 1 +#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." + +#define DRIVER_NAME "mga" +#define DRIVER_DESC "Matrox G200/G400" +#define DRIVER_DATE "20021029" + +#define DRIVER_MAJOR 3 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 0 + +#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 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam, 1, 0 }, + +#define __HAVE_COUNTERS 3 +#define __HAVE_COUNTER6 _DRM_STAT_IRQ +#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY +#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY + /* Driver customization: */ #define DRIVER_PRETAKEDOWN() do { \ @@ -52,6 +80,9 @@ /* DMA customization: */ #define __HAVE_DMA 1 +#define __HAVE_DMA_IRQ 1 +#define __HAVE_VBL_IRQ 1 +#define __HAVE_SHARED_IRQ 1 #define __HAVE_DMA_QUIESCENT 1 #define DRIVER_DMA_QUIESCENT() do { \ diff --git a/sys/dev/drm/mga_dma.c b/sys/dev/drm/mga_dma.c index c6c2236..f04d166 100644 --- a/sys/dev/drm/mga_dma.c +++ b/sys/dev/drm/mga_dma.c @@ -27,7 +27,7 @@ * Authors: * Rickard E. (Rik) Faith <faith@valinux.com> * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -35,17 +35,12 @@ * $FreeBSD$ */ -#define __NO_VERSION__ #include "dev/drm/mga.h" #include "dev/drm/drmP.h" +#include "dev/drm/drm.h" #include "dev/drm/mga_drm.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 @@ -58,7 +53,7 @@ int mga_do_wait_for_idle( drm_mga_private_t *dev_priv ) { u32 status = 0; int i; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK; @@ -66,32 +61,32 @@ int mga_do_wait_for_idle( drm_mga_private_t *dev_priv ) MGA_WRITE8( MGA_CRTC_INDEX, 0 ); return 0; } - DRM_OS_DELAY( 1 ); + DRM_UDELAY( 1 ); } #if MGA_DMA_DEBUG DRM_ERROR( "failed!\n" ); DRM_INFO( " status=0x%08x\n", status ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } int mga_do_dma_idle( drm_mga_private_t *dev_priv ) { u32 status = 0; int i; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); 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 ); + DRM_UDELAY( 1 ); } #if MGA_DMA_DEBUG DRM_ERROR( "failed! status=0x%08x\n", status ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } int mga_do_dma_reset( drm_mga_private_t *dev_priv ) @@ -99,7 +94,7 @@ 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", __func__ ); + DRM_DEBUG( "\n" ); /* The primary DMA stream should look like new right about now. */ @@ -120,13 +115,13 @@ int mga_do_dma_reset( drm_mga_private_t *dev_priv ) int mga_do_engine_reset( drm_mga_private_t *dev_priv ) { - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); /* 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 */ + DRM_UDELAY( 15 ); /* Wait at least 10 usecs */ MGA_WRITE( MGA_RST, 0 ); /* Initialize the registers that get clobbered by the soft @@ -164,8 +159,17 @@ 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", __func__ ); + u32 status = 0; + int i; + DMA_LOCALS; + DRM_DEBUG( "\n" ); + + /* We need to wait so that we can do an safe flush */ + for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { + status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK; + if ( status == MGA_ENDPRDMASTS ) break; + DRM_UDELAY( 1 ); + } if ( primary->tail == primary->last_flush ) { DRM_DEBUG( " bailing out...\n" ); @@ -204,7 +208,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv ) mga_flush_write_combine(); MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); - DRM_DEBUG( "%s: done.\n", __func__ ); + DRM_DEBUG( "done.\n" ); } void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv ) @@ -212,7 +216,7 @@ 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", __func__ ); + DRM_DEBUG( "\n" ); BEGIN_DMA_WRAP(); @@ -247,7 +251,7 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv ) MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); set_bit( 0, &primary->wrapped ); - DRM_DEBUG( "%s: done.\n", __func__ ); + DRM_DEBUG( "done.\n" ); } void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv ) @@ -255,7 +259,7 @@ 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", __func__ ); + DRM_DEBUG( "\n" ); sarea_priv->last_wrap++; DRM_DEBUG( " wrap = %d\n", sarea_priv->last_wrap ); @@ -264,7 +268,7 @@ void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv ) MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL ); clear_bit( 0, &primary->wrapped ); - DRM_DEBUG( "%s: done.\n", __func__ ); + DRM_DEBUG( "done.\n" ); } @@ -304,13 +308,12 @@ static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv ) drm_mga_buf_priv_t *buf_priv; drm_mga_freelist_t *entry; int i; - DRM_DEBUG( "%s: count=%d\n", - __func__, dma->buf_count ); + DRM_DEBUG( "count=%d\n", dma->buf_count ); dev_priv->head = DRM(alloc)( sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER ); if ( dev_priv->head == NULL ) - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) ); SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 ); @@ -322,7 +325,7 @@ static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv ) entry = DRM(alloc)( sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER ); if ( entry == NULL ) - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); memset( entry, 0, sizeof(drm_mga_freelist_t) ); @@ -351,7 +354,7 @@ 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", __func__ ); + DRM_DEBUG( "\n" ); entry = dev_priv->head; while ( entry ) { @@ -389,7 +392,7 @@ static drm_buf_t *mga_freelist_get( drm_device_t *dev ) drm_mga_freelist_t *prev; drm_mga_freelist_t *tail = dev_priv->tail; u32 head, wrap; - DRM_DEBUG( "%s:\n", __func__ ); + DRM_DEBUG( "\n" ); head = MGA_READ( MGA_PRIMADDRESS ); wrap = dev_priv->sarea_priv->last_wrap; @@ -421,8 +424,7 @@ int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ) 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", - __func__, + DRM_DEBUG( "age=0x%06lx wrap=%d\n", buf_priv->list_entry->age.head - dev_priv->primary->offset, buf_priv->list_entry->age.wrap ); @@ -455,18 +457,12 @@ int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ) 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", __func__ ); + DRM_DEBUG( "\n" ); dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER ); if ( !dev_priv ) - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); memset( dev_priv, 0, sizeof(drm_mga_private_t) ); @@ -496,44 +492,23 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) 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__ */ + DRM_GETSAREA(); 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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); if(!dev_priv->mmio) { @@ -541,7 +516,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->status, init->status_offset ); if(!dev_priv->status) { @@ -549,15 +524,16 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->primary, init->primary_offset ); if(!dev_priv->primary) { @@ -565,7 +541,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); if(!dev_priv->buffers) { @@ -573,7 +549,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } dev_priv->sarea_priv = @@ -591,25 +567,25 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } ret = mga_warp_install_microcode( dev_priv ); - if ( ret ) { + 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 ); - return DRM_OS_ERR(ret); + return ret; } ret = mga_warp_init( dev_priv ); - if ( ret ) { + 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 ); - return DRM_OS_ERR(ret); + return ret; } dev_priv->prim.status = (u32 *)dev_priv->status->handle; @@ -641,10 +617,6 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) 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; @@ -657,7 +629,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma( dev ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } /* Make dev_private visable to others. */ @@ -667,7 +639,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) int mga_do_cleanup_dma( drm_device_t *dev ) { - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); if ( dev->dev_private ) { drm_mga_private_t *dev_priv = dev->dev_private; @@ -688,12 +660,12 @@ int mga_do_cleanup_dma( drm_device_t *dev ) return 0; } -int mga_dma_init( DRM_OS_IOCTL ) +int mga_dma_init( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_mga_init_t init; - DRM_OS_KRNFROMUSR( init, (drm_mga_init_t *) data, sizeof(init) ); + DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) ); switch ( init.func ) { case MGA_INIT_DMA: @@ -702,7 +674,7 @@ int mga_dma_init( DRM_OS_IOCTL ) return mga_do_cleanup_dma( dev ); } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } @@ -710,18 +682,17 @@ int mga_dma_init( DRM_OS_IOCTL ) * Primary DMA stream management */ -int mga_dma_flush( DRM_OS_IOCTL ) +int mga_dma_flush( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) ); - DRM_DEBUG( "%s: %s%s%s\n", - __func__, + DRM_DEBUG( "%s%s%s\n", (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "", (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "", (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" ); @@ -735,8 +706,8 @@ int mga_dma_flush( DRM_OS_IOCTL ) if ( lock.flags & _DRM_LOCK_QUIESCENT ) { #if MGA_DMA_DEBUG int ret = mga_do_wait_for_idle( dev_priv ); - if ( ret ) - DRM_INFO( "%s: -EBUSY\n", __func__ ); + if ( ret < 0 ) + DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ ); return ret; #else return mga_do_wait_for_idle( dev_priv ); @@ -746,9 +717,9 @@ int mga_dma_flush( DRM_OS_IOCTL ) } } -int mga_dma_reset( DRM_OS_IOCTL ) +int mga_dma_reset( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; LOCK_TEST_WITH_RETURN( dev ); @@ -761,7 +732,6 @@ int mga_dma_reset( DRM_OS_IOCTL ) * DMA buffer management */ -#if 0 static int mga_dma_get_buffers( drm_device_t *dev, drm_dma_t *d ) { drm_buf_t *buf; @@ -769,52 +739,48 @@ static int mga_dma_get_buffers( drm_device_t *dev, drm_dma_t *d ) for ( i = d->granted_count ; i < d->request_count ; i++ ) { buf = mga_freelist_get( dev ); - if ( !buf ) - return DRM_OS_ERR(EAGAIN); + if ( !buf ) return DRM_ERR(EAGAIN); - buf->pid = current->pid; + buf->pid = DRM_CURRENTPID; - if ( DRM_OS_COPYTOUSR( &d->request_indices[i], + if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx, sizeof(buf->idx) ) ) - return DRM_OS_ERR(EFAULT); - if ( DRM_OS_COPYTOUSR( &d->request_sizes[i], + return DRM_ERR(EFAULT); + if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total, sizeof(buf->total) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); d->granted_count++; } return 0; } -#endif /* 0 */ -int mga_dma_buffers( DRM_OS_IOCTL ) +int mga_dma_buffers( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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) ); + DRM_COPY_FROM_USER_IOCTL( 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 ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, d.send_count ); + return DRM_ERR(EINVAL); } /* We'll send you buffers. */ if ( d.request_count < 0 || d.request_count > dma->buf_count ) { DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n", - DRM_OS_CURRENTPID, d.request_count, dma->buf_count ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, d.request_count, dma->buf_count ); + return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN( dev_priv ); @@ -822,26 +788,10 @@ int mga_dma_buffers( DRM_OS_IOCTL ) 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 ) - return DRM_OS_ERR(EAGAIN); - - buf->pid = DRM_OS_CURRENTPID; - - if ( DRM_OS_COPYTOUSR( &d.request_indices[i], - &buf->idx, sizeof(buf->idx) ) ) - return DRM_OS_ERR(EFAULT); - if ( DRM_OS_COPYTOUSR( &d.request_sizes[i], - &buf->total, sizeof(buf->total) ) ) - return DRM_OS_ERR(EFAULT); - - d.granted_count++; - } - ret = 0; + ret = mga_dma_get_buffers( dev, &d ); } - DRM_OS_KRNTOUSR( (drm_dma_t *) data, d, sizeof(d) ); + DRM_COPY_TO_USER_IOCTL( (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 index 50dc398..d511dac 100644 --- a/sys/dev/drm/mga_drm.h +++ b/sys/dev/drm/mga_drm.h @@ -26,7 +26,7 @@ * * Authors: * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -40,6 +40,7 @@ /* 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__ @@ -223,7 +224,14 @@ typedef struct _drm_mga_sarea { int ctxOwner; } drm_mga_sarea_t; -/* MGA specific ioctls */ + +/* WARNING: If you change any of these defines, make sure to change the + * defines in the Xserver file (xf86drmMga.h) + */ + +/* MGA specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ #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) @@ -233,11 +241,8 @@ typedef struct _drm_mga_sarea { #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) +#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(0x49, drm_mga_getparam_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; @@ -320,4 +325,14 @@ typedef struct _drm_mga_blit { int source_pitch, dest_pitch; } drm_mga_blit_t; +/* 3.1: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define MGA_PARAM_IRQ_NR 1 + +typedef struct drm_mga_getparam { + int param; + int *value; +} drm_mga_getparam_t; + #endif diff --git a/sys/dev/drm/mga_drv.c b/sys/dev/drm/mga_drv.c index 98a3567..aee3cd5 100644 --- a/sys/dev/drm/mga_drv.c +++ b/sys/dev/drm/mga_drv.c @@ -31,37 +31,14 @@ * $FreeBSD$ */ -#ifdef __linux__ -#include <linux/config.h> -#endif /* __linux__ */ - -#ifdef __FreeBSD__ -#include <sys/types.h> -#include <sys/bus.h> -#include <pci/pcivar.h> -#endif /* __FreeBSD__ */ - #include "dev/drm/mga.h" #include "dev/drm/drmP.h" +#include "dev/drm/drm.h" #include "dev/drm/mga_drm.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. +/* List acquired from http://www.yourvote.com/pci/pcihdr.h and xc/xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h + * Please report to anholt@teleport.com inaccuracies or if a chip you have works that is marked unsupported here. */ drm_chipinfo_t DRM(devicelist)[] = { {0x102b, 0x0520, 0, "Matrox G200 (PCI)"}, @@ -70,26 +47,6 @@ drm_chipinfo_t DRM(devicelist)[] = { {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" @@ -98,40 +55,16 @@ drm_chipinfo_t DRM(devicelist)[] = { #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" +#ifdef __FreeBSD__ DRIVER_MODULE(mga, pci, mga_driver, mga_devclass, 0, 0); -#endif /* __FreeBSD__ */ +#elif defined(__NetBSD__) +CFDRIVER_DECL(mga, DV_TTY, NULL); +#endif diff --git a/sys/dev/drm/mga_drv.h b/sys/dev/drm/mga_drv.h index be8ecf9..5772cd6 100644 --- a/sys/dev/drm/mga_drv.h +++ b/sys/dev/drm/mga_drv.h @@ -33,12 +33,6 @@ #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; @@ -54,8 +48,6 @@ typedef struct drm_mga_primary_buffer { u32 last_wrap; u32 high_mark; - - spinlock_t list_lock; } drm_mga_primary_buffer_t; typedef struct drm_mga_freelist { @@ -100,21 +92,21 @@ typedef struct drm_mga_private { 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_local_map_t *sarea; + drm_local_map_t *fb; + drm_local_map_t *mmio; + drm_local_map_t *status; + drm_local_map_t *warp; + drm_local_map_t *primary; + drm_local_map_t *buffers; + drm_local_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_dma_init( DRM_IOCTL_ARGS ); +extern int mga_dma_flush( DRM_IOCTL_ARGS ); +extern int mga_dma_reset( DRM_IOCTL_ARGS ); +extern int mga_dma_buffers( DRM_IOCTL_ARGS ); extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv ); extern int mga_do_dma_idle( drm_mga_private_t *dev_priv ); @@ -129,40 +121,42 @@ 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 ); +extern int mga_dma_clear( DRM_IOCTL_ARGS ); +extern int mga_dma_swap( DRM_IOCTL_ARGS ); +extern int mga_dma_vertex( DRM_IOCTL_ARGS ); +extern int mga_dma_indices( DRM_IOCTL_ARGS ); +extern int mga_dma_iload( DRM_IOCTL_ARGS ); +extern int mga_dma_blit( DRM_IOCTL_ARGS ); +extern int mga_getparam( DRM_IOCTL_ARGS ); /* 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_flush_write_combine() DRM_WRITEMEMORYBARRIER(dev_priv->primary) +#if defined(__linux__) && defined(__alpha__) #define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle)) #define MGA_ADDR( reg ) (MGA_BASE(reg) + reg) #define MGA_DEREF( reg ) *(volatile u32 *)MGA_ADDR( reg ) #define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg ) -#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) +#define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg))) +#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF( reg ) = val; } while (0) +#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(dev_priv->mmio); MGA_DEREF8( reg ) = val; } while (0) static inline u32 _MGA_READ(u32 *addr) { - mb(); + DRM_READMEMORYBARRIER(dev_priv->mmio); 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) +#define MGA_READ8( reg ) DRM_READ8(dev_priv->mmio, (reg)) +#define MGA_READ( reg ) DRM_READ32(dev_priv->mmio, (reg)) +#define MGA_WRITE8( reg, val ) DRM_WRITE8(dev_priv->mmio, (reg), (val)) +#define MGA_WRITE( reg, val ) DRM_WRITE32(dev_priv->mmio, (reg), (val)) #endif #define DWGREG0 0x1c00 @@ -195,9 +189,10 @@ do { \ #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", __func__ ); \ - return DRM_OS_ERR(EINVAL); \ + dev->lock.pid != DRM_CURRENTPID ) { \ + DRM_ERROR( "%s called without lock held\n", \ + __FUNCTION__ ); \ + return DRM_ERR(EINVAL); \ } \ } while (0) @@ -209,8 +204,8 @@ do { \ } else if ( dev_priv->prim.space < \ dev_priv->prim.high_mark ) { \ if ( MGA_DMA_DEBUG ) \ - DRM_INFO( "%s: wrap...\n", __func__ ); \ - return DRM_OS_ERR(EBUSY); \ + DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ + return DRM_ERR(EBUSY); \ } \ } \ } while (0) @@ -218,10 +213,10 @@ do { \ #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_do_wait_for_idle( dev_priv ) < 0 ) { \ if ( MGA_DMA_DEBUG ) \ - DRM_INFO( "%s: wrap...\n", __func__ ); \ - return DRM_OS_ERR(EBUSY); \ + DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ + return DRM_ERR(EBUSY); \ } \ mga_do_dma_wrap_end( dev_priv ); \ } \ @@ -242,7 +237,7 @@ do { \ do { \ if ( MGA_VERBOSE ) { \ DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \ - (n), __func__ ); \ + (n), __FUNCTION__ ); \ DRM_INFO( " space=0x%x req=0x%x\n", \ dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \ } \ @@ -253,7 +248,7 @@ do { \ #define BEGIN_DMA_WRAP() \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( "BEGIN_DMA() in %s\n", __func__ ); \ + DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \ DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \ } \ prim = dev_priv->prim.start; \ @@ -272,7 +267,7 @@ do { \ #define FLUSH_DMA() \ do { \ if ( 0 ) { \ - DRM_INFO( "%s:\n", __func__ ); \ + DRM_INFO( "%s:\n", __FUNCTION__ ); \ DRM_INFO( " tail=0x%06x head=0x%06lx\n", \ dev_priv->prim.tail, \ MGA_READ( MGA_PRIMADDRESS ) - \ @@ -353,6 +348,11 @@ do { \ /* A reduced set of the mga registers. */ #define MGA_CRTC_INDEX 0x1fd4 +#define MGA_CRTC_DATA 0x1fd5 + +/* CRTC11 */ +#define MGA_VINTCLR (1 << 4) +#define MGA_VINTEN (1 << 5) #define MGA_ALPHACTRL 0x2c7c #define MGA_AR0 0x1c60 @@ -424,8 +424,10 @@ do { \ #define MGA_ICLEAR 0x1e18 # define MGA_SOFTRAPICLR (1 << 0) +# define MGA_VLINEICLR (1 << 5) #define MGA_IEN 0x1e1c # define MGA_SOFTRAPIEN (1 << 0) +# define MGA_VLINEIEN (1 << 5) #define MGA_LEN 0x1c5c @@ -464,6 +466,8 @@ do { \ # define MGA_SRCACC_AGP (1 << 1) #define MGA_STATUS 0x1e14 # define MGA_SOFTRAPEN (1 << 0) +# define MGA_VSYNCPEN (1 << 4) +# define MGA_VLINEPEN (1 << 5) # define MGA_DWGENGSTS (1 << 16) # define MGA_ENDPRDMASTS (1 << 17) #define MGA_STENCIL 0x2cc8 diff --git a/sys/dev/drm/mga_irq.c b/sys/dev/drm/mga_irq.c new file mode 100644 index 0000000..9b2b691 --- /dev/null +++ b/sys/dev/drm/mga_irq.c @@ -0,0 +1,102 @@ +/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Eric Anholt <anholt@FreeBSD.org> + * + * $FreeBSD$ + */ + +#include "dev/drm/mga.h" +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/mga_drm.h" +#include "dev/drm/mga_drv.h" + +void mga_dma_service( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + int status; + + status = MGA_READ( MGA_STATUS ); + + /* VBLANK interrupt */ + if ( status & MGA_VLINEPEN ) { + MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR ); + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + DRM(vbl_send_signals)( dev ); + } +} + +int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence) +{ + unsigned int cur_vblank; + int ret = 0; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + - *sequence ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +void mga_driver_irq_preinstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); + /* Clear bits if they're already high */ + MGA_WRITE( MGA_ICLEAR, ~0 ); +} + +void mga_driver_irq_postinstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + + /* Turn on VBL interrupt */ + MGA_WRITE( MGA_IEN, MGA_VLINEIEN ); +} + +void mga_driver_irq_uninstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); + } +} diff --git a/sys/dev/drm/mga_state.c b/sys/dev/drm/mga_state.c index f1b7ac1..2f44db3 100644 --- a/sys/dev/drm/mga_state.c +++ b/sys/dev/drm/mga_state.c @@ -26,7 +26,7 @@ * * Authors: * Jeff Hartmann <jhartmann@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * Rewritten by: * Gareth Hughes <gareth@valinux.com> @@ -34,12 +34,11 @@ * $FreeBSD$ */ -#define __NO_VERSION__ #include "dev/drm/mga.h" #include "dev/drm/drmP.h" +#include "dev/drm/drm.h" #include "dev/drm/mga_drm.h" #include "dev/drm/mga_drv.h" -#include "dev/drm/drm.h" /* ================================================================ @@ -166,6 +165,9 @@ static __inline__ void mga_g400_emit_tex0( drm_mga_private_t *dev_priv ) drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; DMA_LOCALS; +/* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */ +/* tex->texctl, tex->texctl2); */ + BEGIN_DMA( 6 ); DMA_BLOCK( MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC, @@ -207,6 +209,9 @@ static __inline__ void mga_g400_emit_tex1( drm_mga_private_t *dev_priv ) drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1]; DMA_LOCALS; +/* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */ +/* tex->texctl, tex->texctl2); */ + BEGIN_DMA( 5 ); DMA_BLOCK( MGA_TEXCTL2, (tex->texctl2 | @@ -275,6 +280,8 @@ static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv ) unsigned int pipe = sarea_priv->warp_pipe; DMA_LOCALS; +/* printk("mga_g400_emit_pipe %x\n", pipe); */ + BEGIN_DMA( 10 ); DMA_BLOCK( MGA_WIADDR2, MGA_WMODE_SUSPEND, @@ -415,7 +422,7 @@ static int mga_verify_context( drm_mga_private_t *dev_priv ) ctx->dstorg, dev_priv->front_offset, dev_priv->back_offset ); ctx->dstorg = 0; - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } return 0; @@ -435,7 +442,7 @@ static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit ) DRM_ERROR( "*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit ); tex->texorg = 0; - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } return 0; @@ -477,13 +484,13 @@ static int mga_verify_iload( drm_mga_private_t *dev_priv, dstorg + length > (dev_priv->texture_offset + dev_priv->texture_size) ) { DRM_ERROR( "*** bad iload DSTORG: 0x%x\n", dstorg ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( length & MGA_ILOAD_MASK ) { DRM_ERROR( "*** bad iload length: 0x%x\n", length & MGA_ILOAD_MASK ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } return 0; @@ -496,7 +503,7 @@ static int mga_verify_blit( drm_mga_private_t *dev_priv, (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) { DRM_ERROR( "*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } return 0; } @@ -516,7 +523,7 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int nbox = sarea_priv->nbox; int i; DMA_LOCALS; - DRM_DEBUG( "%s:\n", __func__ ); + DRM_DEBUG( "\n" ); BEGIN_DMA( 1 ); @@ -610,7 +617,7 @@ static void mga_dma_dispatch_swap( drm_device_t *dev ) int nbox = sarea_priv->nbox; int i; DMA_LOCALS; - DRM_DEBUG( "%s:\n", __func__ ); + DRM_DEBUG( "\n" ); sarea_priv->last_frame.head = dev_priv->prim.tail; sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; @@ -656,7 +663,7 @@ static void mga_dma_dispatch_swap( drm_device_t *dev ) FLUSH_DMA(); - DRM_DEBUG( "%s... done.\n", __func__ ); + DRM_DEBUG( "%s... done.\n", __FUNCTION__ ); } static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf ) @@ -764,8 +771,7 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf, u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM; u32 y2; DMA_LOCALS; - DRM_DEBUG( "%s: buf=%d used=%d\n", - __func__, buf->idx, buf->used ); + DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used ); y2 = length / 64; @@ -819,7 +825,7 @@ static void mga_dma_dispatch_blit( drm_device_t *dev, int nbox = sarea_priv->nbox; u32 scandir = 0, i; DMA_LOCALS; - DRM_DEBUG( "%s:\n", __func__ ); + DRM_DEBUG( "\n" ); BEGIN_DMA( 4 + nbox ); @@ -876,16 +882,16 @@ static void mga_dma_dispatch_blit( drm_device_t *dev, * */ -int mga_dma_clear( DRM_OS_IOCTL ) +int mga_dma_clear( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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) ); + DRM_COPY_FROM_USER_IOCTL( clear, (drm_mga_clear_t *)data, sizeof(clear) ); if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; @@ -901,9 +907,9 @@ int mga_dma_clear( DRM_OS_IOCTL ) return 0; } -int mga_dma_swap( DRM_OS_IOCTL ) +int mga_dma_swap( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; @@ -923,9 +929,9 @@ int mga_dma_swap( DRM_OS_IOCTL ) return 0; } -int mga_dma_vertex( DRM_OS_IOCTL ) +int mga_dma_vertex( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; @@ -934,9 +940,11 @@ int mga_dma_vertex( DRM_OS_IOCTL ) LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( vertex, (drm_mga_vertex_t *) data, sizeof(vertex) ); + DRM_COPY_FROM_USER_IOCTL( vertex, + (drm_mga_vertex_t *)data, + sizeof(vertex) ); - if(vertex.idx < 0 || vertex.idx > dma->buf_count) return DRM_OS_ERR(EINVAL); + if(vertex.idx < 0 || vertex.idx > dma->buf_count) return DRM_ERR(EINVAL); buf = dma->buflist[vertex.idx]; buf_priv = buf->dev_private; @@ -950,7 +958,7 @@ int mga_dma_vertex( DRM_OS_IOCTL ) buf_priv->dispatched = 0; mga_freelist_put( dev, buf ); } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN( dev_priv ); @@ -960,9 +968,9 @@ int mga_dma_vertex( DRM_OS_IOCTL ) return 0; } -int mga_dma_indices( DRM_OS_IOCTL ) +int mga_dma_indices( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; @@ -971,9 +979,11 @@ int mga_dma_indices( DRM_OS_IOCTL ) LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( indices, (drm_mga_indices_t *) data, sizeof(indices) ); + DRM_COPY_FROM_USER_IOCTL( indices, + (drm_mga_indices_t *)data, + sizeof(indices) ); - if(indices.idx < 0 || indices.idx > dma->buf_count) return DRM_OS_ERR(EINVAL); + if(indices.idx < 0 || indices.idx > dma->buf_count) return DRM_ERR(EINVAL); buf = dma->buflist[indices.idx]; buf_priv = buf->dev_private; @@ -987,7 +997,7 @@ int mga_dma_indices( DRM_OS_IOCTL ) buf_priv->dispatched = 0; mga_freelist_put( dev, buf ); } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN( dev_priv ); @@ -997,35 +1007,35 @@ int mga_dma_indices( DRM_OS_IOCTL ) return 0; } -int mga_dma_iload( DRM_OS_IOCTL ) +int mga_dma_iload( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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( "%s:\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( iload, (drm_mga_iload_t *) data, sizeof(iload) ); + DRM_COPY_FROM_USER_IOCTL( iload, (drm_mga_iload_t *)data, sizeof(iload) ); #if 0 - if ( mga_do_wait_for_idle( dev_priv ) ) { + if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { if ( MGA_DMA_DEBUG ) - DRM_INFO( "%s: -EBUSY\n", __func__ ); - return DRM_OS_ERR(EBUSY); + DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ ); + return DRM_ERR(EBUSY); } #endif - if(iload.idx < 0 || iload.idx > dma->buf_count) return DRM_OS_ERR(EINVAL); + if(iload.idx < 0 || iload.idx > dma->buf_count) return DRM_ERR(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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN( dev_priv ); @@ -1039,23 +1049,23 @@ int mga_dma_iload( DRM_OS_IOCTL ) return 0; } -int mga_dma_blit( DRM_OS_IOCTL ) +int mga_dma_blit( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( blit, (drm_mga_blit_t *) data, sizeof(blit) ); + DRM_COPY_FROM_USER_IOCTL( 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 ) ) - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); WRAP_TEST_WITH_RETURN( dev_priv ); @@ -1067,3 +1077,36 @@ int mga_dma_blit( DRM_OS_IOCTL ) return 0; } + +int mga_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_mga_private_t *dev_priv = dev->dev_private; + drm_mga_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case MGA_PARAM_IRQ_NR: + value = dev->irq; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} diff --git a/sys/dev/drm/mga_warp.c b/sys/dev/drm/mga_warp.c index 7e94b6a..06aa833 100644 --- a/sys/dev/drm/mga_warp.c +++ b/sys/dev/drm/mga_warp.c @@ -32,6 +32,7 @@ #define __NO_VERSION__ #include "dev/drm/mga.h" #include "dev/drm/drmP.h" +#include "dev/drm/drm.h" #include "dev/drm/mga_drm.h" #include "dev/drm/mga_drv.h" #include "dev/drm/mga_ucode.h" @@ -108,7 +109,7 @@ static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv ) if ( size > dev_priv->warp->size ) { DRM_ERROR( "microcode too large! (%u > %lu)\n", size, dev_priv->warp->size ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } memset( dev_priv->warp_pipe_phys, 0, @@ -145,7 +146,7 @@ static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv ) if ( size > dev_priv->warp->size ) { DRM_ERROR( "microcode too large! (%u > %lu)\n", size, dev_priv->warp->size ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } memset( dev_priv->warp_pipe_phys, 0, @@ -171,7 +172,7 @@ int mga_warp_install_microcode( drm_mga_private_t *dev_priv ) case MGA_CARD_TYPE_G200: return mga_warp_install_g200_microcode( dev_priv ); default: - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } } @@ -196,7 +197,7 @@ int mga_warp_init( drm_mga_private_t *dev_priv ) MGA_WRITE( MGA_WVRTXSZ, 7 ); break; default: - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } MGA_WRITE( MGA_WMISC, (MGA_WUCODECACHE_ENABLE | @@ -206,7 +207,7 @@ int mga_warp_init( drm_mga_private_t *dev_priv ) if ( wmisc != WMISC_EXPECTED ) { DRM_ERROR( "WARP engine config failed! 0x%x != 0x%x\n", wmisc, WMISC_EXPECTED ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } return 0; diff --git a/sys/dev/drm/r128.h b/sys/dev/drm/r128.h index 8bcf10c..29ca828 100644 --- a/sys/dev/drm/r128.h +++ b/sys/dev/drm/r128.h @@ -45,6 +45,36 @@ #define __HAVE_SG 1 #define __HAVE_PCI_DMA 1 +#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." + +#define DRIVER_NAME "r128" +#define DRIVER_DESC "ATI Rage 128" +#define DRIVER_DATE "20021029" + +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 3 +#define DRIVER_PATCHLEVEL 0 + + +#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 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)] = { r128_getparam, 1, 0 }, + /* Driver customization: */ #define DRIVER_PRERELEASE() do { \ @@ -63,6 +93,9 @@ /* DMA customization: */ #define __HAVE_DMA 1 +#define __HAVE_DMA_IRQ 1 +#define __HAVE_VBL_IRQ 1 +#define __HAVE_SHARED_IRQ 1 #if 0 /* GH: Remove this for now... */ diff --git a/sys/dev/drm/r128_cce.c b/sys/dev/drm/r128_cce.c index 092242c..910f3d1 100644 --- a/sys/dev/drm/r128_cce.c +++ b/sys/dev/drm/r128_cce.c @@ -30,21 +30,14 @@ * $FreeBSD$ */ -#define __NO_VERSION__ #include "dev/drm/r128.h" #include "dev/drm/drmP.h" +#include "dev/drm/drm.h" #include "dev/drm/r128_drm.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, @@ -90,6 +83,7 @@ static u32 r128_cce_microcode[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ); int R128_READ_PLL(drm_device_t *dev, int addr) { @@ -134,13 +128,13 @@ static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv ) if ( !(R128_READ( R128_PC_NGUI_CTLSTAT ) & R128_PC_BUSY) ) { return 0; } - DRM_OS_DELAY( 1 ); + DRM_UDELAY( 1 ); } #if R128_FIFO_DEBUG - DRM_ERROR( "%s failed!\n", __func__ ); + DRM_ERROR( "failed!\n" ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries ) @@ -150,13 +144,13 @@ static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries ) 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 ); + DRM_UDELAY( 1 ); } #if R128_FIFO_DEBUG - DRM_ERROR( "%s failed!\n", __func__ ); + DRM_ERROR( "failed!\n" ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ) @@ -171,13 +165,13 @@ int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ) r128_do_pixcache_flush( dev_priv ); return 0; } - DRM_OS_DELAY( 1 ); + DRM_UDELAY( 1 ); } #if R128_FIFO_DEBUG - DRM_ERROR( "%s failed!\n", __func__ ); + DRM_ERROR( "failed!\n" ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } @@ -190,7 +184,7 @@ static void r128_cce_load_microcode( drm_r128_private_t *dev_priv ) { int i; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); r128_do_wait_for_idle( dev_priv ); @@ -231,14 +225,14 @@ int r128_do_cce_idle( drm_r128_private_t *dev_priv ) return r128_do_pixcache_flush( dev_priv ); } } - DRM_OS_DELAY( 1 ); + DRM_UDELAY( 1 ); } #if R128_FIFO_DEBUG DRM_ERROR( "failed!\n" ); r128_status( dev_priv ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } /* Start the Concurrent Command Engine. @@ -326,7 +320,7 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev, u32 ring_start; u32 tmp; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); /* The manual (p. 2) says this address is in "VM space". This * means it's an offset from the start of AGP space. @@ -346,12 +340,9 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev, /* 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; @@ -365,7 +356,6 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev, entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } -#endif /* Set watermark control */ R128_WRITE( R128_PM4_BUFFER_WM_CNTL, @@ -385,18 +375,12 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev, 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", __func__ ); + DRM_DEBUG( "\n" ); dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); if ( dev_priv == NULL ) - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); memset( dev_priv, 0, sizeof(drm_r128_private_t) ); @@ -406,7 +390,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) DRM_ERROR( "PCI GART memory not allocated!\n" ); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } dev_priv->usec_timeout = init->usec_timeout; @@ -415,7 +399,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) DRM_DEBUG( "TIMEOUT problem!\n" ); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } dev_priv->cce_mode = init->cce_mode; @@ -435,7 +419,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) DRM_DEBUG( "Bad cce_mode!\n" ); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } switch ( init->cce_mode ) { @@ -497,33 +481,13 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) 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__ */ - + DRM_GETSAREA(); + if(!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->fb, init->fb_offset ); @@ -531,35 +495,35 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) DRM_ERROR("could not find framebuffer!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( !dev_priv->is_pci ) { @@ -569,7 +533,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) DRM_ERROR("could not find agp texture region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } } @@ -587,7 +551,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) DRM_ERROR("Could not ioremap agp regions!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } } else { dev_priv->cce_ring->handle = @@ -617,6 +581,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = 128; + dev_priv->ring.ring_rptr = dev_priv->ring_rptr; dev_priv->sarea_priv->last_frame = 0; R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame ); @@ -632,7 +597,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) DRM_ERROR( "failed to init PCI GART!\n" ); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart ); } @@ -676,14 +641,14 @@ int r128_do_cleanup_cce( drm_device_t *dev ) return 0; } -int r128_cce_init( DRM_OS_IOCTL ) +int r128_cce_init( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_init_t init; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); - DRM_OS_KRNFROMUSR( init, (drm_r128_init_t *)data, sizeof(init) ); + DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) ); switch ( init.func ) { case R128_INIT_CCE: @@ -692,19 +657,19 @@ int r128_cce_init( DRM_OS_IOCTL ) return r128_do_cleanup_cce( dev ); } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } -int r128_cce_start( DRM_OS_IOCTL ) +int r128_cce_start( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) { - DRM_DEBUG( "%s while CCE running\n", __func__ ); + DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ ); return 0; } @@ -716,17 +681,17 @@ int r128_cce_start( DRM_OS_IOCTL ) /* Stop the CCE. The engine must have been idled before calling this * routine. */ -int r128_cce_stop( DRM_OS_IOCTL ) +int r128_cce_stop( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_cce_stop_t stop; int ret; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR(stop, (drm_r128_cce_stop_t *)data, sizeof(stop) ); + DRM_COPY_FROM_USER_IOCTL(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. @@ -740,12 +705,7 @@ int r128_cce_stop( DRM_OS_IOCTL ) */ 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, @@ -762,17 +722,17 @@ int r128_cce_stop( DRM_OS_IOCTL ) /* Just reset the CCE ring. Called as part of an X Server engine reset. */ -int r128_cce_reset( DRM_OS_IOCTL ) +int r128_cce_reset( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); if ( !dev_priv ) { - DRM_DEBUG( "%s called before init done\n", __func__ ); - return DRM_OS_ERR(EINVAL); + DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); } r128_do_cce_reset( dev_priv ); @@ -783,11 +743,11 @@ int r128_cce_reset( DRM_OS_IOCTL ) return 0; } -int r128_cce_idle( DRM_OS_IOCTL ) +int r128_cce_idle( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); @@ -798,10 +758,10 @@ int r128_cce_idle( DRM_OS_IOCTL ) return r128_do_cce_idle( dev_priv ); } -int r128_engine_reset( DRM_OS_IOCTL ) +int r128_engine_reset( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEVICE; + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); @@ -816,7 +776,7 @@ int r128_engine_reset( DRM_OS_IOCTL ) static int r128_do_init_pageflip( drm_device_t *dev ) { drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET ); dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL ); @@ -834,7 +794,7 @@ static int r128_do_init_pageflip( drm_device_t *dev ) int r128_do_cleanup_pageflip( drm_device_t *dev ) { drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); @@ -845,14 +805,14 @@ int r128_do_cleanup_pageflip( drm_device_t *dev ) return 0; } -int r128_fullscreen( DRM_OS_IOCTL ) +int r128_fullscreen( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_fullscreen_t fs; LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( fs, (drm_r128_fullscreen_t *)data, sizeof(fs) ); + DRM_COPY_FROM_USER_IOCTL( fs, (drm_r128_fullscreen_t *)data, sizeof(fs) ); switch ( fs.func ) { case R128_INIT_FULLSCREEN: @@ -861,7 +821,7 @@ int r128_fullscreen( DRM_OS_IOCTL ) return r128_do_cleanup_pageflip( dev ); } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } @@ -884,7 +844,7 @@ static int r128_freelist_init( drm_device_t *dev ) dev_priv->head = DRM(alloc)( sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER ); if ( dev_priv->head == NULL ) - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) ); dev_priv->head->age = R128_BUFFER_USED; @@ -895,7 +855,7 @@ static int r128_freelist_init( drm_device_t *dev ) entry = DRM(alloc)( sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER ); - if ( !entry ) return DRM_OS_ERR(ENOMEM); + if ( !entry ) return DRM_ERR(ENOMEM); entry->age = R128_BUFFER_FREE; entry->buf = buf; @@ -950,7 +910,7 @@ drm_buf_t *r128_freelist_get( drm_device_t *dev ) return buf; } } - DRM_OS_DELAY( 1 ); + DRM_UDELAY( 1 ); } DRM_ERROR( "returning NULL!\n" ); @@ -983,61 +943,62 @@ int r128_wait_ring( drm_r128_private_t *dev_priv, int n ) r128_update_ring_snapshot( ring ); if ( ring->space >= n ) return 0; - DRM_OS_DELAY( 1 ); + DRM_UDELAY( 1 ); } /* FIXME: This is being ignored... */ DRM_ERROR( "failed!\n" ); - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } -static int r128_cce_get_buffers( drm_device_t *dev, drm_dma_t *d) +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 ) return DRM_OS_ERR(EAGAIN); + if ( !buf ) return DRM_ERR(EAGAIN); - buf->pid = DRM_OS_CURRENTPID; + buf->pid = DRM_CURRENTPID; - if ( DRM_OS_COPYTOUSR( &d->request_indices[i], &buf->idx, + if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx, sizeof(buf->idx) ) ) - return DRM_OS_ERR(EFAULT); - if ( DRM_OS_COPYTOUSR( &d->request_sizes[i], &buf->total, + return DRM_ERR(EFAULT); + if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total, sizeof(buf->total) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); + d->granted_count++; } return 0; } -int r128_cce_buffers( DRM_OS_IOCTL ) +int r128_cce_buffers( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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) ); + DRM_COPY_FROM_USER_IOCTL( 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 ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, d.send_count ); + return DRM_ERR(EINVAL); } /* We'll send you buffers. */ if ( d.request_count < 0 || d.request_count > dma->buf_count ) { DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n", - DRM_OS_CURRENTPID, d.request_count, dma->buf_count ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, d.request_count, dma->buf_count ); + return DRM_ERR(EINVAL); } d.granted_count = 0; @@ -1046,7 +1007,7 @@ int r128_cce_buffers( DRM_OS_IOCTL ) ret = r128_cce_get_buffers( dev, &d ); } - DRM_OS_KRNTOUSR((drm_dma_t *) data, d, sizeof(d) ); + DRM_COPY_TO_USER_IOCTL((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 index dc53ea0..be26ca4 100644 --- a/sys/dev/drm/r128_drm.h +++ b/sys/dev/drm/r128_drm.h @@ -173,7 +173,9 @@ typedef struct drm_r128_sarea { * defines in the Xserver file (xf86drmR128.h) */ -/* Rage 128 specific ioctls */ +/* Rage 128 specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ #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) @@ -189,6 +191,8 @@ typedef struct drm_r128_sarea { #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) +#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOW( 0x52, drm_r128_getparam_t) typedef struct drm_r128_init { enum { @@ -304,4 +308,14 @@ typedef struct drm_r128_fullscreen { } func; } drm_r128_fullscreen_t; +/* 2.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define R128_PARAM_IRQ_NR 1 + +typedef struct drm_r128_getparam { + int param; + int *value; +} drm_r128_getparam_t; + #endif diff --git a/sys/dev/drm/r128_drv.c b/sys/dev/drm/r128_drv.c index 9361d0b..611014e 100644 --- a/sys/dev/drm/r128_drv.c +++ b/sys/dev/drm/r128_drv.c @@ -31,53 +31,31 @@ * $FreeBSD$ */ -#ifdef __linux__ -#include <linux/config.h> -#endif /* __linux__ */ - -#ifdef __FreeBSD__ -#include <sys/types.h> -#include <sys/bus.h> -#include <pci/pcivar.h> -#endif /* __FreeBSD__ */ - #include "dev/drm/r128.h" #include "dev/drm/drmP.h" +#include "dev/drm/drm.h" #include "dev/drm/r128_drm.h" #include "dev/drm/r128_drv.h" #if __REALLY_HAVE_SG -#include "ati_pcigart.h" +#include "dev/drm/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. +/* List acquired from http://www.yourvote.com/pci/pcihdr.h and xc/xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h + * Please report to eta@lclark.edu inaccuracies or if a chip you have works that is marked unsupported here. */ -/* PCI cards are not supported with DRI under FreeBSD. */ drm_chipinfo_t DRM(devicelist)[] = { - {0x1002, 0x4c45, 0, "ATI Rage 128 Mobility LE (PCI)"}, + {0x1002, 0x4c45, __REALLY_HAVE_SG, "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, 0x5044, __REALLY_HAVE_SG, "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, 0x5050, __REALLY_HAVE_SG, "ATI Rage 128 Pro PP (PCI)"}, + {0x1002, 0x5052, __REALLY_HAVE_SG, "ATI Rage 128 Pro PR (PCI)"}, + {0x1002, 0x5245, __REALLY_HAVE_SG, "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, 0x524b, __REALLY_HAVE_SG, "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)"}, @@ -85,36 +63,6 @@ drm_chipinfo_t DRM(devicelist)[] = { {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" @@ -123,45 +71,19 @@ drm_chipinfo_t DRM(devicelist)[] = { #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 +#if __HAVE_SG #include "dev/drm/drm_scatter.h" #endif #ifdef __FreeBSD__ DRIVER_MODULE(r128, pci, r128_driver, r128_devclass, 0, 0); +#elif defined(__NetBSD__) +CFDRIVER_DECL(r128, DV_TTY, NULL); #endif /* __FreeBSD__ */ diff --git a/sys/dev/drm/r128_drv.h b/sys/dev/drm/r128_drv.h index a10fd14..325c453 100644 --- a/sys/dev/drm/r128_drv.h +++ b/sys/dev/drm/r128_drv.h @@ -33,22 +33,11 @@ * $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 ) +#define GET_RING_HEAD(ring) DRM_READ32( (ring)->ring_rptr, 0 ) /* (ring)->head */ +#define SET_RING_HEAD(ring,val) DRM_WRITE32( (ring)->ring_rptr, 0, (val) ) /* (ring)->head */ typedef struct drm_r128_freelist { unsigned int age; @@ -69,6 +58,7 @@ typedef struct drm_r128_ring_buffer { int space; int high_mark; + drm_local_map_t *ring_rptr; } drm_r128_ring_buffer_t; typedef struct drm_r128_private { @@ -85,9 +75,7 @@ typedef struct drm_r128_private { 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; @@ -113,13 +101,13 @@ typedef struct drm_r128_private { 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_local_map_t *sarea; + drm_local_map_t *fb; + drm_local_map_t *mmio; + drm_local_map_t *cce_ring; + drm_local_map_t *ring_rptr; + drm_local_map_t *buffers; + drm_local_map_t *agp_textures; } drm_r128_private_t; typedef struct drm_r128_buf_priv { @@ -131,14 +119,15 @@ typedef struct drm_r128_buf_priv { } 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 int r128_cce_init( DRM_IOCTL_ARGS ); +extern int r128_cce_start( DRM_IOCTL_ARGS ); +extern int r128_cce_stop( DRM_IOCTL_ARGS ); +extern int r128_cce_reset( DRM_IOCTL_ARGS ); +extern int r128_cce_idle( DRM_IOCTL_ARGS ); +extern int r128_engine_reset( DRM_IOCTL_ARGS ); +extern int r128_fullscreen( DRM_IOCTL_ARGS ); +extern int r128_cce_buffers( DRM_IOCTL_ARGS ); +extern int r128_getparam( DRM_IOCTL_ARGS ); extern void r128_freelist_reset( drm_device_t *dev ); extern drm_buf_t *r128_freelist_get( drm_device_t *dev ); @@ -158,14 +147,14 @@ 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 ); +extern int r128_cce_clear( DRM_IOCTL_ARGS ); +extern int r128_cce_swap( DRM_IOCTL_ARGS ); +extern int r128_cce_vertex( DRM_IOCTL_ARGS ); +extern int r128_cce_indices( DRM_IOCTL_ARGS ); +extern int r128_cce_blit( DRM_IOCTL_ARGS ); +extern int r128_cce_depth( DRM_IOCTL_ARGS ); +extern int r128_cce_stipple( DRM_IOCTL_ARGS ); +extern int r128_cce_indirect( DRM_IOCTL_ARGS ); /* Register definitions, register access macros and drmAddMap constants @@ -228,6 +217,11 @@ extern int r128_cce_indirect( DRM_OS_IOCTL ); #define R128_DST_PITCH_OFFSET_C 0x1c80 # define R128_DST_TILE (1 << 31) +#define R128_GEN_INT_CNTL 0x0040 +# define R128_CRTC_VBLANK_INT_EN (1 << 0) +#define R128_GEN_INT_STATUS 0x0044 +# define R128_CRTC_VBLANK_INT (1 << 0) +# define R128_CRTC_VBLANK_INT_AK (1 << 0) #define R128_GEN_RESET_CNTL 0x00f0 # define R128_SOFT_RESET_GUI (1 << 0) @@ -379,48 +373,10 @@ extern int r128_cce_indirect( DRM_OS_IOCTL ); #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_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) +#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) +#define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) +#define R128_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) #define R128_WRITE_PLL(addr,val) \ do { \ @@ -448,9 +404,9 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); #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", __func__ ); \ - return DRM_OS_ERR(EINVAL); \ + dev->lock.pid != DRM_CURRENTPID ) { \ + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); \ + return DRM_ERR(EINVAL); \ } \ } while (0) @@ -462,10 +418,10 @@ do { \ r128_update_ring_snapshot( ring ); \ if ( ring->space >= ring->high_mark ) \ goto __ring_space_done; \ - DRM_OS_DELAY( 1 ); \ + DRM_UDELAY(1); \ } \ DRM_ERROR( "ring space check failed!\n" ); \ - return DRM_OS_ERR(EBUSY); \ + return DRM_ERR(EBUSY); \ } \ __ring_space_done: \ ; \ @@ -476,7 +432,7 @@ 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; \ + if ( __ret ) return __ret; \ sarea_priv->last_dispatch = 0; \ r128_freelist_reset( dev ); \ } \ @@ -492,7 +448,11 @@ do { \ * Ring control */ -#define r128_flush_write_combine() DRM_OS_READMEMORYBARRIER +#if defined(__powerpc__) +#define r128_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring ) +#else +#define r128_flush_write_combine() DRM_WRITEMEMORYBARRIER(dev_priv->ring_rptr) +#endif #define R128_VERBOSE 0 @@ -503,7 +463,7 @@ do { \ #define BEGIN_RING( n ) do { \ if ( R128_VERBOSE ) { \ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ - (n), __func__ ); \ + (n), __FUNCTION__ ); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ r128_wait_ring( dev_priv, (n) * sizeof(u32) ); \ diff --git a/sys/dev/drm/r128_irq.c b/sys/dev/drm/r128_irq.c new file mode 100644 index 0000000..5fb8f22 --- /dev/null +++ b/sys/dev/drm/r128_irq.c @@ -0,0 +1,102 @@ +/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Eric Anholt <anholt@FreeBSD.org> + * + * $FreeBSD$ + */ + +#include "dev/drm/r128.h" +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/r128_drm.h" +#include "dev/drm/r128_drv.h" + +void r128_dma_service( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + int status; + + status = R128_READ( R128_GEN_INT_STATUS ); + + /* VBLANK interrupt */ + if ( status & R128_CRTC_VBLANK_INT ) { + R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK ); + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + DRM(vbl_send_signals)( dev ); + } +} + +int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) +{ + unsigned int cur_vblank; + int ret = 0; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + - *sequence ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +void r128_driver_irq_preinstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); + /* Clear vblank bit if it's already high */ + R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK ); +} + +void r128_driver_irq_postinstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + + /* Turn on VBL interrupt */ + R128_WRITE( R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN ); +} + +void r128_driver_irq_uninstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); + } +} diff --git a/sys/dev/drm/r128_state.c b/sys/dev/drm/r128_state.c index 94ba460..fc2095f 100644 --- a/sys/dev/drm/r128_state.c +++ b/sys/dev/drm/r128_state.c @@ -29,17 +29,11 @@ * $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/drm.h" #include "dev/drm/r128_drm.h" #include "dev/drm/r128_drv.h" -#include "dev/drm/drm.h" - /* ================================================================ @@ -51,7 +45,7 @@ static void r128_emit_clip_rects( drm_r128_private_t *dev_priv, { u32 aux_sc_cntl = 0x00000000; RING_LOCALS; - DRM_DEBUG( " %s\n", __func__ ); + DRM_DEBUG( " %s\n", __FUNCTION__ ); BEGIN_RING( 17 ); @@ -94,7 +88,7 @@ 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", __func__ ); + DRM_DEBUG( " %s\n", __FUNCTION__ ); BEGIN_RING( 2 ); @@ -109,7 +103,7 @@ 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", __func__ ); + DRM_DEBUG( " %s\n", __FUNCTION__ ); BEGIN_RING( 13 ); @@ -135,7 +129,7 @@ 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", __func__ ); + DRM_DEBUG( " %s\n", __FUNCTION__ ); BEGIN_RING( 3 ); @@ -151,7 +145,7 @@ 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", __func__ ); + DRM_DEBUG( " %s\n", __FUNCTION__ ); BEGIN_RING( 5 ); @@ -170,7 +164,7 @@ 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", __func__ ); + DRM_DEBUG( " %s\n", __FUNCTION__ ); BEGIN_RING( 2 ); @@ -187,7 +181,7 @@ static __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv ) drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0]; int i; RING_LOCALS; - DRM_DEBUG( " %s\n", __func__ ); + DRM_DEBUG( " %s\n", __FUNCTION__ ); BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS ); @@ -213,7 +207,7 @@ static __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv ) drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1]; int i; RING_LOCALS; - DRM_DEBUG( " %s\n", __func__ ); + DRM_DEBUG( " %s\n", __FUNCTION__ ); BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS ); @@ -236,7 +230,7 @@ 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", __func__, dirty ); + DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty ); if ( dirty & R128_UPLOAD_CORE ) { r128_emit_core( dev_priv ); @@ -377,7 +371,7 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, unsigned int flags = clear->flags; int i; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "%s\n", __FUNCTION__ ); if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { unsigned int tmp = flags; @@ -480,7 +474,7 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) drm_clip_rect_t *pbox = sarea_priv->boxes; int i; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "%s\n", __FUNCTION__ ); #if R128_PERFORMANCE_BOXES /* Do some trivial performance monitoring... @@ -536,7 +530,7 @@ 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", __func__, dev_priv->current_page ); + DRM_DEBUG( "page=%d\n", dev_priv->current_page ); #if R128_PERFORMANCE_BOXES /* Do some trivial performance monitoring... @@ -585,8 +579,7 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, int prim = buf_priv->prim; int i = 0; RING_LOCALS; - DRM_DEBUG( "%s: buf=%d nbox=%d\n", - __func__, buf->idx, sarea_priv->nbox ); + DRM_DEBUG( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox ); if ( 0 ) r128_print_dirty( "dispatch_vertex", sarea_priv->dirty ); @@ -788,7 +781,7 @@ static void r128_cce_dispatch_indices( drm_device_t *dev, } static int r128_cce_dispatch_blit( drm_device_t *dev, - drm_r128_blit_t *blit, int pid ) + drm_r128_blit_t *blit ) { drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; @@ -797,7 +790,7 @@ static int r128_cce_dispatch_blit( drm_device_t *dev, u32 *data; int dword_shift, dwords; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll @@ -818,7 +811,7 @@ static int r128_cce_dispatch_blit( drm_device_t *dev, break; default: DRM_ERROR( "invalid blit format %d\n", blit->format ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } /* Flush the pixel cache, and mark the contents as Read Invalid. @@ -838,14 +831,14 @@ static int r128_cce_dispatch_blit( drm_device_t *dev, buf = dma->buflist[blit->idx]; buf_priv = buf->dev_private; - if ( buf->pid != pid ) { + if ( buf->pid != DRM_CURRENTPID ) { DRM_ERROR( "process %d using buffer owned by %d\n", - pid, buf->pid ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", blit->idx ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } buf_priv->discard = 1; @@ -905,38 +898,38 @@ static int r128_cce_dispatch_write_span( drm_device_t *dev, int count, x, y; u32 *buffer; u8 *mask; - int i; + int i, buffer_size, mask_size; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); count = depth->n; - if ( DRM_OS_COPYFROMUSR( &x, depth->x, sizeof(x) ) ) { - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) { + return DRM_ERR(EFAULT); } - if ( DRM_OS_COPYFROMUSR( &y, depth->y, sizeof(y) ) ) { - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) { + return DRM_ERR(EFAULT); } - buffer = DRM_OS_MALLOC( depth->n * sizeof(u32) ); + buffer_size = depth->n * sizeof(u32); + buffer = DRM_MALLOC( buffer_size ); if ( buffer == NULL ) - return DRM_OS_ERR(ENOMEM); - if ( DRM_OS_COPYFROMUSR( buffer, depth->buffer, - depth->n * sizeof(u32) ) ) { - DRM_OS_FREE( buffer ); - return DRM_OS_ERR(EFAULT); + return DRM_ERR(ENOMEM); + if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) { + DRM_FREE( buffer, buffer_size); + return DRM_ERR(EFAULT); } + mask_size = depth->n * sizeof(u8); if ( depth->mask ) { - mask = DRM_OS_MALLOC( depth->n * sizeof(u8) ); + mask = DRM_MALLOC( mask_size ); if ( mask == NULL ) { - DRM_OS_FREE( buffer ); - return DRM_OS_ERR(ENOMEM); + DRM_FREE( buffer, buffer_size ); + return DRM_ERR(ENOMEM); } - if ( DRM_OS_COPYFROMUSR( mask, depth->mask, - depth->n * sizeof(u8) ) ) { - DRM_OS_FREE( buffer ); - DRM_OS_FREE( mask ); - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) { + DRM_FREE( buffer, buffer_size ); + DRM_FREE( mask, mask_size ); + return DRM_ERR(EFAULT); } for ( i = 0 ; i < count ; i++, x++ ) { @@ -962,7 +955,7 @@ static int r128_cce_dispatch_write_span( drm_device_t *dev, } } - DRM_OS_FREE( mask ); + DRM_FREE( mask, mask_size ); } else { for ( i = 0 ; i < count ; i++, x++ ) { BEGIN_RING( 6 ); @@ -986,7 +979,7 @@ static int r128_cce_dispatch_write_span( drm_device_t *dev, } } - DRM_OS_FREE( buffer ); + DRM_FREE( buffer, buffer_size ); return 0; } @@ -998,61 +991,63 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev, int count, *x, *y; u32 *buffer; u8 *mask; - int i; + int i, xbuf_size, ybuf_size, buffer_size, mask_size; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); count = depth->n; - x = DRM_OS_MALLOC( count * sizeof(*x) ); + xbuf_size = count * sizeof(*x); + ybuf_size = count * sizeof(*y); + x = DRM_MALLOC( xbuf_size ); if ( x == NULL ) { - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } - y = DRM_OS_MALLOC( count * sizeof(*y) ); + y = DRM_MALLOC( ybuf_size ); if ( y == NULL ) { - DRM_OS_FREE( x ); - return DRM_OS_ERR(ENOMEM); + DRM_FREE( x, xbuf_size ); + return DRM_ERR(ENOMEM); } - if ( DRM_OS_COPYFROMUSR( x, depth->x, count * sizeof(int) ) ) { - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + return DRM_ERR(EFAULT); } - if ( DRM_OS_COPYFROMUSR( y, depth->y, count * sizeof(int) ) ) { - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( y, depth->y, xbuf_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + return DRM_ERR(EFAULT); } - buffer = DRM_OS_MALLOC( depth->n * sizeof(u32) ); + buffer_size = depth->n * sizeof(u32); + buffer = DRM_MALLOC( buffer_size ); if ( buffer == NULL ) { - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); - return DRM_OS_ERR(ENOMEM); + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + return DRM_ERR(ENOMEM); } - if ( DRM_OS_COPYFROMUSR( buffer, depth->buffer, - depth->n * sizeof(u32) ) ) { - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); - DRM_OS_FREE( buffer ); - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + DRM_FREE( buffer, buffer_size ); + return DRM_ERR(EFAULT); } if ( depth->mask ) { - mask = DRM_OS_MALLOC( depth->n * sizeof(u8) ); + mask_size = depth->n * sizeof(u8); + mask = DRM_MALLOC( mask_size ); if ( mask == NULL ) { - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); - DRM_OS_FREE( buffer ); - return DRM_OS_ERR(ENOMEM); + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + DRM_FREE( buffer, buffer_size ); + return DRM_ERR(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 ); - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + DRM_FREE( buffer, buffer_size ); + DRM_FREE( mask, mask_size ); + return DRM_ERR(EFAULT); } for ( i = 0 ; i < count ; i++ ) { @@ -1078,7 +1073,7 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev, } } - DRM_OS_FREE( mask ); + DRM_FREE( mask, mask_size ); } else { for ( i = 0 ; i < count ; i++ ) { BEGIN_RING( 6 ); @@ -1102,9 +1097,9 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev, } } - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); - DRM_OS_FREE( buffer ); + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + DRM_FREE( buffer, buffer_size ); return 0; } @@ -1115,14 +1110,14 @@ static int r128_cce_dispatch_read_span( drm_device_t *dev, drm_r128_private_t *dev_priv = dev->dev_private; int count, x, y; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); count = depth->n; - if ( DRM_OS_COPYFROMUSR( &x, depth->x, sizeof(x) ) ) { - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) { + return DRM_ERR(EFAULT); } - if ( DRM_OS_COPYFROMUSR( &y, depth->y, sizeof(y) ) ) { - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) { + return DRM_ERR(EFAULT); } BEGIN_RING( 7 ); @@ -1155,33 +1150,35 @@ static int r128_cce_dispatch_read_pixels( drm_device_t *dev, { drm_r128_private_t *dev_priv = dev->dev_private; int count, *x, *y; - int i; + int i, xbuf_size, ybuf_size; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + 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) ); + xbuf_size = count * sizeof(*x); + ybuf_size = count * sizeof(*y); + x = DRM_MALLOC( xbuf_size ); if ( x == NULL ) { - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } - y = DRM_OS_MALLOC( count * sizeof(*y) ); + y = DRM_MALLOC( ybuf_size ); if ( y == NULL ) { - DRM_OS_FREE( x ); - return DRM_OS_ERR(ENOMEM); + DRM_FREE( x, xbuf_size ); + return DRM_ERR(ENOMEM); } - if ( DRM_OS_COPYFROMUSR( x, depth->x, count * sizeof(int) ) ) { - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + return DRM_ERR(EFAULT); } - if ( DRM_OS_COPYFROMUSR( y, depth->y, count * sizeof(int) ) ) { - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) { + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); + return DRM_ERR(EFAULT); } for ( i = 0 ; i < count ; i++ ) { @@ -1208,8 +1205,8 @@ static int r128_cce_dispatch_read_pixels( drm_device_t *dev, ADVANCE_RING(); } - DRM_OS_FREE( x ); - DRM_OS_FREE( y ); + DRM_FREE( x, xbuf_size ); + DRM_FREE( y, ybuf_size ); return 0; } @@ -1224,7 +1221,7 @@ 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", __func__ ); + DRM_DEBUG( "%s\n", __FUNCTION__ ); BEGIN_RING( 33 ); @@ -1241,17 +1238,17 @@ static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple ) * IOCTL functions */ -int r128_cce_clear( DRM_OS_IOCTL ) +int r128_cce_clear( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( clear, (drm_r128_clear_t *) data, + DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t *) data, sizeof(clear) ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1268,12 +1265,12 @@ int r128_cce_clear( DRM_OS_IOCTL ) return 0; } -int r128_cce_swap( DRM_OS_IOCTL ) +int r128_cce_swap( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "%s\n", __FUNCTION__ ); LOCK_TEST_WITH_RETURN( dev ); @@ -1293,9 +1290,9 @@ int r128_cce_swap( DRM_OS_IOCTL ) return 0; } -int r128_cce_vertex( DRM_OS_IOCTL ) +int r128_cce_vertex( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; @@ -1305,26 +1302,26 @@ int r128_cce_vertex( DRM_OS_IOCTL ) LOCK_TEST_WITH_RETURN( dev ); if ( !dev_priv ) { - DRM_ERROR( "%s called with no initialization\n", __func__ ); - return DRM_OS_ERR(EINVAL); + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); } - DRM_OS_KRNFROMUSR( vertex, (drm_r128_vertex_t *) data, + DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t *) data, sizeof(vertex) ); - DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n", - __func__, DRM_OS_CURRENTPID, + DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n", + DRM_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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( vertex.prim < 0 || vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) { DRM_ERROR( "buffer prim %d\n", vertex.prim ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1333,14 +1330,14 @@ int r128_cce_vertex( DRM_OS_IOCTL ) buf = dma->buflist[vertex.idx]; buf_priv = buf->dev_private; - if ( buf->pid != DRM_OS_CURRENTPID ) { + if ( buf->pid != DRM_CURRENTPID ) { DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_OS_CURRENTPID, buf->pid ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", vertex.idx ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } buf->used = vertex.count; @@ -1352,9 +1349,9 @@ int r128_cce_vertex( DRM_OS_IOCTL ) return 0; } -int r128_cce_indices( DRM_OS_IOCTL ) +int r128_cce_indices( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; @@ -1365,26 +1362,25 @@ int r128_cce_indices( DRM_OS_IOCTL ) LOCK_TEST_WITH_RETURN( dev ); if ( !dev_priv ) { - DRM_ERROR( "%s called with no initialization\n", __func__ ); - return DRM_OS_ERR(EINVAL); + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); } - DRM_OS_KRNFROMUSR( elts, (drm_r128_indices_t *) data, + DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t *) data, sizeof(elts) ); - DRM_DEBUG( "%s: pid=%d buf=%d s=%d e=%d d=%d\n", - __func__, DRM_OS_CURRENTPID, + DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( elts.prim < 0 || elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) { DRM_ERROR( "buffer prim %d\n", elts.prim ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1393,14 +1389,14 @@ int r128_cce_indices( DRM_OS_IOCTL ) buf = dma->buflist[elts.idx]; buf_priv = buf->dev_private; - if ( buf->pid != DRM_OS_CURRENTPID ) { + if ( buf->pid != DRM_CURRENTPID ) { DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_OS_CURRENTPID, buf->pid ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", elts.idx ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } count = (elts.end - elts.start) / sizeof(u16); @@ -1408,11 +1404,11 @@ int r128_cce_indices( DRM_OS_IOCTL ) if ( elts.start & 0x7 ) { DRM_ERROR( "misaligned buffer 0x%x\n", elts.start ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( elts.start < buf->used ) { DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } buf->used = elts.end; @@ -1424,42 +1420,41 @@ int r128_cce_indices( DRM_OS_IOCTL ) return 0; } -int r128_cce_blit( DRM_OS_IOCTL ) +int r128_cce_blit( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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, + DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t *) data, sizeof(blit) ); - DRM_DEBUG( "%s: pid=%d index=%d\n", - __func__, DRM_OS_CURRENTPID, blit.idx ); + DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx ); if ( blit.idx < 0 || blit.idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", blit.idx, dma->buf_count - 1 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); + return r128_cce_dispatch_blit( dev, &blit ); } -int r128_cce_depth( DRM_OS_IOCTL ) +int r128_cce_depth( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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, + DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t *) data, sizeof(depth) ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1475,24 +1470,24 @@ int r128_cce_depth( DRM_OS_IOCTL ) return r128_cce_dispatch_read_pixels( dev, &depth ); } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } -int r128_cce_stipple( DRM_OS_IOCTL ) +int r128_cce_stipple( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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, + DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t *) data, sizeof(stipple) ); - if ( DRM_OS_COPYFROMUSR( &mask, stipple.mask, + if ( DRM_COPY_FROM_USER( &mask, stipple.mask, 32 * sizeof(u32) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR( EFAULT ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1501,9 +1496,9 @@ int r128_cce_stipple( DRM_OS_IOCTL ) return 0; } -int r128_cce_indirect( DRM_OS_IOCTL ) +int r128_cce_indirect( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; @@ -1516,11 +1511,11 @@ int r128_cce_indirect( DRM_OS_IOCTL ) LOCK_TEST_WITH_RETURN( dev ); if ( !dev_priv ) { - DRM_ERROR( "%s called with no initialization\n", __func__ ); - return DRM_OS_ERR(EINVAL); + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); } - DRM_OS_KRNFROMUSR( indirect, (drm_r128_indirect_t *) data, + DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t *) data, sizeof(indirect) ); DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n", @@ -1530,26 +1525,26 @@ int r128_cce_indirect( DRM_OS_IOCTL ) if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", indirect.idx, dma->buf_count - 1 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } buf = dma->buflist[indirect.idx]; buf_priv = buf->dev_private; - if ( buf->pid != DRM_OS_CURRENTPID ) { + if ( buf->pid != DRM_CURRENTPID ) { DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_OS_CURRENTPID, buf->pid ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", indirect.idx ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( indirect.start < buf->used ) { DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n", indirect.start, buf->used ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1575,3 +1570,36 @@ int r128_cce_indirect( DRM_OS_IOCTL ) return 0; } + +int r128_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case R128_PARAM_IRQ_NR: + value = dev->irq; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} diff --git a/sys/dev/drm/radeon.h b/sys/dev/drm/radeon.h index f30f069..afb0e53 100644 --- a/sys/dev/drm/radeon.h +++ b/sys/dev/drm/radeon.h @@ -25,6 +25,7 @@ * * Authors: * Gareth Hughes <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * $FreeBSD$ */ @@ -45,39 +46,112 @@ #define __HAVE_SG 1 #define __HAVE_PCI_DMA 1 -/* Driver customization: +#define DRIVER_AUTHOR "Gareth Hughes, Keith Whitwell, others." + +#define DRIVER_NAME "radeon" +#define DRIVER_DESC "ATI Radeon" +#define DRIVER_DATE "20020828" + +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 8 +#define DRIVER_PATCHLEVEL 0 + +/* Interface history: + * + * 1.1 - ?? + * 1.2 - Add vertex2 ioctl (keith) + * - Add stencil capability to clear ioctl (gareth, keith) + * - Increase MAX_TEXTURE_LEVELS (brian) + * 1.3 - Add cmdbuf ioctl (keith) + * - Add support for new radeon packets (keith) + * - Add getparam ioctl (keith) + * - Add flip-buffers ioctl, deprecate fullscreen foo (keith). + * 1.4 - Add scratch registers to get_param ioctl. + * 1.5 - Add r200 packets to cmdbuf ioctl + * - Add r200 function to init ioctl + * - Add 'scalar2' instruction to cmdbuf + * 1.6 - Add static agp memory manager + * Add irq handler (won't be turned on unless X server knows to) + * Add irq ioctls and irq_active getparam. + * Add wait command for cmdbuf ioctl + * Add agp offset query for getparam + * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5] + * and R200_PP_CUBIC_OFFSET_F1_[0..5]. + * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and + * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian) + * 1.8 - Remove need to call cleanup ioctls on last client exit (keith) + */ +#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 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)] = { radeon_mem_free, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)] = { radeon_mem_init_heap, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, + + + +/* When a client dies: + * - Check for and clean up flipped page state + * - Free any alloced agp memory. + * + * DRM infrastructure takes care of reclaiming dma buffers. */ -#define DRIVER_PRERELEASE() do { \ +#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 ); \ } \ + radeon_mem_release( dev_priv->agp_heap ); \ + radeon_mem_release( dev_priv->fb_heap ); \ } \ } while (0) -#define DRIVER_PRETAKEDOWN() do { \ - if ( dev->dev_private ) radeon_do_cleanup_cp( dev ); \ +/* When the last client dies, shut down the CP and free dev->dev_priv. + */ +#define __HAVE_RELEASE 1 +#define DRIVER_RELEASE() \ +do { \ + DRM(reclaim_buffers)( dev, priv->pid ); \ + if ( dev->open_count == 1) \ + radeon_do_release( dev ); \ } while (0) + + /* DMA customization: */ #define __HAVE_DMA 1 +#define __HAVE_DMA_IRQ 1 +#define __HAVE_VBL_IRQ 1 +#define __HAVE_SHARED_IRQ 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 ) \ +#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 index 16b03cb..112e2f6 100644 --- a/sys/dev/drm/radeon_cp.c +++ b/sys/dev/drm/radeon_cp.c @@ -32,22 +32,13 @@ #include "dev/drm/radeon.h" #include "dev/drm/drmP.h" +#include "dev/drm/drm.h" #include "dev/drm/radeon_drm.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__) +#if defined(__alpha__) || defined(__powerpc__) # define PCIGART_ENABLED #else # undef PCIGART_ENABLED @@ -55,6 +46,266 @@ /* CP microcode (from ATI) */ +static u32 R200_cp_microcode[][2] = { + { 0x21007000, 0000000000 }, + { 0x20007000, 0000000000 }, + { 0x000000ab, 0x00000004 }, + { 0x000000af, 0x00000004 }, + { 0x66544a49, 0000000000 }, + { 0x49494174, 0000000000 }, + { 0x54517d83, 0000000000 }, + { 0x498d8b64, 0000000000 }, + { 0x49494949, 0000000000 }, + { 0x49da493c, 0000000000 }, + { 0x49989898, 0000000000 }, + { 0xd34949d5, 0000000000 }, + { 0x9dc90e11, 0000000000 }, + { 0xce9b9b9b, 0000000000 }, + { 0x000f0000, 0x00000016 }, + { 0x352e232c, 0000000000 }, + { 0x00000013, 0x00000004 }, + { 0x000f0000, 0x00000016 }, + { 0x352e272c, 0000000000 }, + { 0x000f0001, 0x00000016 }, + { 0x3239362f, 0000000000 }, + { 0x000077ef, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00000016, 0x00000004 }, + { 0x0003802a, 0x00000002 }, + { 0x040067e0, 0x00000002 }, + { 0x00000016, 0x00000004 }, + { 0x000077e0, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x000037e1, 0x00000002 }, + { 0x040067e1, 0x00000006 }, + { 0x000077e0, 0x00000002 }, + { 0x000077e1, 0x00000002 }, + { 0x000077e1, 0x00000006 }, + { 0xffffffff, 0000000000 }, + { 0x10000000, 0000000000 }, + { 0x0003802a, 0x00000002 }, + { 0x040067e0, 0x00000006 }, + { 0x00007675, 0x00000002 }, + { 0x00007676, 0x00000002 }, + { 0x00007677, 0x00000002 }, + { 0x00007678, 0x00000006 }, + { 0x0003802b, 0x00000002 }, + { 0x04002676, 0x00000002 }, + { 0x00007677, 0x00000002 }, + { 0x00007678, 0x00000006 }, + { 0x0000002e, 0x00000018 }, + { 0x0000002e, 0x00000018 }, + { 0000000000, 0x00000006 }, + { 0x0000002f, 0x00000018 }, + { 0x0000002f, 0x00000018 }, + { 0000000000, 0x00000006 }, + { 0x01605000, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x00098000, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x64c0603d, 0x00000004 }, + { 0x00080000, 0x00000016 }, + { 0000000000, 0000000000 }, + { 0x0400251d, 0x00000002 }, + { 0x00007580, 0x00000002 }, + { 0x00067581, 0x00000002 }, + { 0x04002580, 0x00000002 }, + { 0x00067581, 0x00000002 }, + { 0x00000046, 0x00000004 }, + { 0x00005000, 0000000000 }, + { 0x00061000, 0x00000002 }, + { 0x0000750e, 0x00000002 }, + { 0x00019000, 0x00000002 }, + { 0x00011055, 0x00000014 }, + { 0x00000055, 0x00000012 }, + { 0x0400250f, 0x00000002 }, + { 0x0000504a, 0x00000004 }, + { 0x00007565, 0x00000002 }, + { 0x00007566, 0x00000002 }, + { 0x00000051, 0x00000004 }, + { 0x01e655b4, 0x00000002 }, + { 0x4401b0dc, 0x00000002 }, + { 0x01c110dc, 0x00000002 }, + { 0x2666705d, 0x00000018 }, + { 0x040c2565, 0x00000002 }, + { 0x0000005d, 0x00000018 }, + { 0x04002564, 0x00000002 }, + { 0x00007566, 0x00000002 }, + { 0x00000054, 0x00000004 }, + { 0x00401060, 0x00000008 }, + { 0x00101000, 0x00000002 }, + { 0x000d80ff, 0x00000002 }, + { 0x00800063, 0x00000008 }, + { 0x000f9000, 0x00000002 }, + { 0x000e00ff, 0x00000002 }, + { 0000000000, 0x00000006 }, + { 0x00000080, 0x00000018 }, + { 0x00000054, 0x00000004 }, + { 0x00007576, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x00009000, 0x00000002 }, + { 0x00041000, 0x00000002 }, + { 0x0c00350e, 0x00000002 }, + { 0x00049000, 0x00000002 }, + { 0x00051000, 0x00000002 }, + { 0x01e785f8, 0x00000002 }, + { 0x00200000, 0x00000002 }, + { 0x00600073, 0x0000000c }, + { 0x00007563, 0x00000002 }, + { 0x006075f0, 0x00000021 }, + { 0x20007068, 0x00000004 }, + { 0x00005068, 0x00000004 }, + { 0x00007576, 0x00000002 }, + { 0x00007577, 0x00000002 }, + { 0x0000750e, 0x00000002 }, + { 0x0000750f, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00600076, 0x0000000c }, + { 0x006075f0, 0x00000021 }, + { 0x000075f8, 0x00000002 }, + { 0x00000076, 0x00000004 }, + { 0x000a750e, 0x00000002 }, + { 0x0020750f, 0x00000002 }, + { 0x00600079, 0x00000004 }, + { 0x00007570, 0x00000002 }, + { 0x00007571, 0x00000002 }, + { 0x00007572, 0x00000006 }, + { 0x00005000, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00007568, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x00000084, 0x0000000c }, + { 0x00058000, 0x00000002 }, + { 0x0c607562, 0x00000002 }, + { 0x00000086, 0x00000004 }, + { 0x00600085, 0x00000004 }, + { 0x400070dd, 0000000000 }, + { 0x000380dd, 0x00000002 }, + { 0x00000093, 0x0000001c }, + { 0x00065095, 0x00000018 }, + { 0x040025bb, 0x00000002 }, + { 0x00061096, 0x00000018 }, + { 0x040075bc, 0000000000 }, + { 0x000075bb, 0x00000002 }, + { 0x000075bc, 0000000000 }, + { 0x00090000, 0x00000006 }, + { 0x00090000, 0x00000002 }, + { 0x000d8002, 0x00000006 }, + { 0x00005000, 0x00000002 }, + { 0x00007821, 0x00000002 }, + { 0x00007800, 0000000000 }, + { 0x00007821, 0x00000002 }, + { 0x00007800, 0000000000 }, + { 0x01665000, 0x00000002 }, + { 0x000a0000, 0x00000002 }, + { 0x000671cc, 0x00000002 }, + { 0x0286f1cd, 0x00000002 }, + { 0x000000a3, 0x00000010 }, + { 0x21007000, 0000000000 }, + { 0x000000aa, 0x0000001c }, + { 0x00065000, 0x00000002 }, + { 0x000a0000, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x000b0000, 0x00000002 }, + { 0x38067000, 0x00000002 }, + { 0x000a00a6, 0x00000004 }, + { 0x20007000, 0000000000 }, + { 0x01200000, 0x00000002 }, + { 0x20077000, 0x00000002 }, + { 0x01200000, 0x00000002 }, + { 0x20007000, 0000000000 }, + { 0x00061000, 0x00000002 }, + { 0x0120751b, 0x00000002 }, + { 0x8040750a, 0x00000002 }, + { 0x8040750b, 0x00000002 }, + { 0x00110000, 0x00000002 }, + { 0x000380dd, 0x00000002 }, + { 0x000000bd, 0x0000001c }, + { 0x00061096, 0x00000018 }, + { 0x844075bd, 0x00000002 }, + { 0x00061095, 0x00000018 }, + { 0x840075bb, 0x00000002 }, + { 0x00061096, 0x00000018 }, + { 0x844075bc, 0x00000002 }, + { 0x000000c0, 0x00000004 }, + { 0x804075bd, 0x00000002 }, + { 0x800075bb, 0x00000002 }, + { 0x804075bc, 0x00000002 }, + { 0x00108000, 0x00000002 }, + { 0x01400000, 0x00000002 }, + { 0x006000c4, 0x0000000c }, + { 0x20c07000, 0x00000020 }, + { 0x000000c6, 0x00000012 }, + { 0x00800000, 0x00000006 }, + { 0x0080751d, 0x00000006 }, + { 0x000025bb, 0x00000002 }, + { 0x000040c0, 0x00000004 }, + { 0x0000775c, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00661000, 0x00000002 }, + { 0x0460275d, 0x00000020 }, + { 0x00004000, 0000000000 }, + { 0x00007999, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00661000, 0x00000002 }, + { 0x0460299b, 0x00000020 }, + { 0x00004000, 0000000000 }, + { 0x01e00830, 0x00000002 }, + { 0x21007000, 0000000000 }, + { 0x00005000, 0x00000002 }, + { 0x00038042, 0x00000002 }, + { 0x040025e0, 0x00000002 }, + { 0x000075e1, 0000000000 }, + { 0x00000001, 0000000000 }, + { 0x000380d9, 0x00000002 }, + { 0x04007394, 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 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, +}; + + static u32 radeon_cp_microcode[][2] = { { 0x21007000, 0000000000 }, { 0x20007000, 0000000000 }, @@ -326,7 +577,7 @@ int RADEON_READ_PLL(drm_device_t *dev, int addr) #if RADEON_FIFO_DEBUG static void radeon_status( drm_radeon_private_t *dev_priv ) { - printk( "%s:\n", __func__ ); + printk( "%s:\n", __FUNCTION__ ); printk( "RBBM_STATUS = 0x%08x\n", (unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) ); printk( "CP_RB_RTPR = 0x%08x\n", @@ -356,6 +607,8 @@ static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv ) u32 tmp; int i; + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + tmp = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT ); tmp |= RADEON_RB2D_DC_FLUSH_ALL; RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp ); @@ -365,14 +618,14 @@ static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv ) & RADEON_RB2D_DC_BUSY) ) { return 0; } - DRM_OS_DELAY( 1 ); + DRM_UDELAY( 1 ); } #if RADEON_FIFO_DEBUG DRM_ERROR( "failed!\n" ); radeon_status( dev_priv ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv, @@ -380,40 +633,45 @@ static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv, { int i; + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + 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 ); + DRM_UDELAY( 1 ); } #if RADEON_FIFO_DEBUG DRM_ERROR( "failed!\n" ); radeon_status( dev_priv ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv ) { int i, ret; + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + ret = radeon_do_wait_for_fifo( dev_priv, 64 ); if ( ret ) return ret; + 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 ); + DRM_UDELAY( 1 ); } #if RADEON_FIFO_DEBUG DRM_ERROR( "failed!\n" ); radeon_status( dev_priv ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } @@ -425,16 +683,31 @@ static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv ) static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv ) { int i; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); 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] ); + + if (dev_priv->is_r200) + { + DRM_INFO("Loading R200 Microcode\n"); + for ( i = 0 ; i < 256 ; i++ ) + { + RADEON_WRITE( RADEON_CP_ME_RAM_DATAH, + R200_cp_microcode[i][1] ); + RADEON_WRITE( RADEON_CP_ME_RAM_DATAL, + R200_cp_microcode[i][0] ); + } + } + else + { + 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] ); + } } } @@ -444,7 +717,7 @@ static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv ) */ static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv ) { - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); #if 0 u32 tmp; @@ -458,7 +731,7 @@ static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv ) int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ) { RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); BEGIN_RING( 6 ); @@ -467,6 +740,7 @@ int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ) RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); + COMMIT_RING(); return radeon_do_wait_for_idle( dev_priv ); } @@ -476,7 +750,7 @@ int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ) static void radeon_do_cp_start( drm_radeon_private_t *dev_priv ) { RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); radeon_do_wait_for_idle( dev_priv ); @@ -491,6 +765,7 @@ static void radeon_do_cp_start( drm_radeon_private_t *dev_priv ) RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING(); + COMMIT_RING(); } /* Reset the Command Processor. This will not flush any pending @@ -500,7 +775,7 @@ static void radeon_do_cp_start( drm_radeon_private_t *dev_priv ) static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv ) { u32 cur_read_ptr; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR ); RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr ); @@ -514,7 +789,7 @@ static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv ) */ static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv ) { - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); @@ -527,7 +802,7 @@ 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", __func__ ); + DRM_DEBUG( "\n" ); radeon_do_pixcache_flush( dev_priv ); @@ -619,12 +894,9 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, *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; @@ -638,10 +910,59 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } -#endif + + /* Initialize the scratch register pointer. This will cause + * the scratch register values to be written out to memory + * whenever they are updated. + * + * We simply put this behind the ring read pointer, this works + * with PCI GART as well as (whatever kind of) AGP GART + */ + RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR ) + + RADEON_SCRATCH_REG_OFFSET ); + + dev_priv->scratch = ((__volatile__ u32 *) + dev_priv->ring.head + + (RADEON_SCRATCH_REG_OFFSET / sizeof(u32))); + + RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 ); + + /* Writeback doesn't seem to work everywhere, test it first */ + DRM_WRITE32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0 ); + RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef ); + + for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) { + if ( DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(1) ) == 0xdeadbeef ) + break; + DRM_UDELAY( 1 ); + } + + if ( tmp < dev_priv->usec_timeout ) { + dev_priv->writeback_works = 1; + DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp ); + } else { + dev_priv->writeback_works = 0; + DRM_DEBUG( "writeback test failed\n" ); + } + + dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; + RADEON_WRITE( RADEON_LAST_FRAME_REG, + dev_priv->sarea_priv->last_frame ); + + dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0; + RADEON_WRITE( RADEON_LAST_DISPATCH_REG, + dev_priv->sarea_priv->last_dispatch ); + + dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; + RADEON_WRITE( RADEON_LAST_CLEAR_REG, + dev_priv->sarea_priv->last_clear ); /* Set ring buffer size */ +#ifdef __BIG_ENDIAN + RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT ); +#else RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw ); +#endif radeon_do_wait_for_idle( dev_priv ); @@ -660,18 +981,12 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, 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", __func__ ); + DRM_DEBUG( "\n" ); dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); if ( dev_priv == NULL ) - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); memset( dev_priv, 0, sizeof(drm_radeon_private_t) ); @@ -684,7 +999,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_ERROR( "PCI GART not yet supported for Radeon!\n" ); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } #endif @@ -692,7 +1007,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_ERROR( "PCI GART memory not allocated!\n" ); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } dev_priv->usec_timeout = init->usec_timeout; @@ -701,15 +1016,13 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_DEBUG( "TIMEOUT problem!\n" ); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } + dev_priv->is_r200 = (init->func == RADEON_INIT_R200_CP); + dev_priv->do_boxes = 0; 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. @@ -719,7 +1032,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode ); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } switch ( init->fb_bpp ) { @@ -761,17 +1074,17 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) * 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); + (1<<15)); - 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.rb3d_zstencilcntl = + (dev_priv->depth_fmt | + RADEON_Z_TEST_ALWAYS | + RADEON_STENCIL_TEST_ALWAYS | + RADEON_STENCIL_S_FAIL_REPLACE | + RADEON_STENCIL_ZPASS_REPLACE | + RADEON_STENCIL_ZFAIL_REPLACE | + RADEON_Z_WRITE_ENABLE); dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW | RADEON_BFACE_SOLID | @@ -785,33 +1098,13 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) 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__ */ - + DRM_GETSAREA(); + if(!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->fb, init->fb_offset ); @@ -819,35 +1112,35 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_ERROR("could not find framebuffer!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( !dev_priv->is_pci ) { @@ -857,7 +1150,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_ERROR("could not find agp texture region!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } } @@ -875,7 +1168,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_ERROR("could not find ioremap agp regions!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } } else { dev_priv->cp_ring->handle = @@ -926,34 +1219,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) (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 ); + dev_priv->ring.ring_rptr = dev_priv->ring_rptr; #if __REALLY_HAVE_SG if ( dev_priv->is_pci ) { @@ -962,7 +1228,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_ERROR( "failed to init PCI GART!\n" ); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); - return DRM_OS_ERR(ENOMEM); + return DRM_ERR(ENOMEM); } /* Turn on PCI GART */ @@ -985,7 +1251,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */ RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */ } else { -#endif +#endif /* __REALLY_HAVE_SG */ /* Turn off PCI GART */ tmp = RADEON_READ( RADEON_AIC_CNTL ) @@ -993,14 +1259,12 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) RADEON_WRITE( RADEON_AIC_CNTL, tmp ); #if __REALLY_HAVE_SG } -#endif +#endif /* __REALLY_HAVE_SG */ 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; @@ -1011,25 +1275,23 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) int radeon_do_cleanup_cp( drm_device_t *dev ) { - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); 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 __REALLY_HAVE_SG 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 /* __REALLY_HAVE_SG */ } -#endif DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); @@ -1039,38 +1301,39 @@ int radeon_do_cleanup_cp( drm_device_t *dev ) return 0; } -int radeon_cp_init( DRM_OS_IOCTL ) +int radeon_cp_init( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_radeon_init_t init; - DRM_OS_KRNFROMUSR( init, (drm_radeon_init_t *) data, sizeof(init) ); + DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) ); switch ( init.func ) { case RADEON_INIT_CP: + case RADEON_INIT_R200_CP: return radeon_do_init_cp( dev, &init ); case RADEON_CLEANUP_CP: return radeon_do_cleanup_cp( dev ); } - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } -int radeon_cp_start( DRM_OS_IOCTL ) +int radeon_cp_start( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); if ( dev_priv->cp_running ) { - DRM_DEBUG( "%s while CP running\n", __func__ ); + 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", - __func__, dev_priv->cp_mode ); + __FUNCTION__, dev_priv->cp_mode ); return 0; } @@ -1082,17 +1345,20 @@ int radeon_cp_start( DRM_OS_IOCTL ) /* Stop the CP. The engine must have been idled before calling this * routine. */ -int radeon_cp_stop( DRM_OS_IOCTL ) +int radeon_cp_stop( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_cp_stop_t stop; int ret; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( stop, (drm_radeon_cp_stop_t *) data, sizeof(stop) ); + DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t *)data, sizeof(stop) ); + + if (!dev_priv->cp_running) + return 0; /* Flush any pending CP commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. @@ -1121,19 +1387,52 @@ int radeon_cp_stop( DRM_OS_IOCTL ) return 0; } + +void radeon_do_release( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int ret; + + if (dev_priv) { + if (dev_priv->cp_running) { + /* Stop the cp */ + while ((ret = radeon_do_cp_idle( dev_priv )) != 0) { + DRM_DEBUG("radeon_do_cp_idle %d\n", ret); +#ifdef __linux__ + schedule(); +#else + tsleep(&ret, PZERO, "rdnrel", 1); +#endif + } + radeon_do_cp_stop( dev_priv ); + radeon_do_engine_reset( dev ); + } + + /* Disable *all* interrupts */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + + /* Free memory heap structures */ + radeon_mem_takedown( &(dev_priv->agp_heap) ); + radeon_mem_takedown( &(dev_priv->fb_heap) ); + + /* deallocate kernel resources */ + radeon_do_cleanup_cp( dev ); + } +} + /* Just reset the CP ring. Called as part of an X Server engine reset. */ -int radeon_cp_reset( DRM_OS_IOCTL ) +int radeon_cp_reset( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); if ( !dev_priv ) { - DRM_DEBUG( "%s called before init done\n", __func__ ); - return DRM_OS_ERR(EINVAL); + DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); } radeon_do_cp_reset( dev_priv ); @@ -1144,21 +1443,21 @@ int radeon_cp_reset( DRM_OS_IOCTL ) return 0; } -int radeon_cp_idle( DRM_OS_IOCTL ) +int radeon_cp_idle( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); return radeon_do_cp_idle( dev_priv ); } -int radeon_engine_reset( DRM_OS_IOCTL ) +int radeon_engine_reset( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEVICE; + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); @@ -1170,114 +1469,74 @@ int radeon_engine_reset( DRM_OS_IOCTL ) * Fullscreen mode */ -static int radeon_do_init_pageflip( drm_device_t *dev ) +/* KW: Deprecated to say the least: + */ +int radeon_fullscreen( DRM_IOCTL_ARGS ) { - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG( "%s\n", __func__ ); - - 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", __func__ ); - - 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 ); - } - - return DRM_OS_ERR(EINVAL); -} - /* ================================================================ * Freelist management */ -#define RADEON_BUFFER_USED 0xffffffff -#define RADEON_BUFFER_FREE 0 -#if 0 -static int radeon_freelist_init( drm_device_t *dev ) +/* Original comment: FIXME: ROTATE_BUFS is a hack 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. + * + * KW: It's also a good way to find free buffers quickly. + * + * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't + * sleep. However, bugs in older versions of radeon_accel.c mean that + * we essentially have to do this, else old clients will break. + * + * However, it does leave open a potential deadlock where all the + * buffers are held by other clients, which can't release them because + * they can't get the lock. + */ + +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_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 ) - return DRM_OS_ERR(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 ) return DRM_OS_ERR(ENOMEM); + drm_buf_t *buf; + int i, t; + int start; - 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; + if ( ++dev_priv->last_buf >= dma->buf_count ) + dev_priv->last_buf = 0; - buf_priv->discard = 0; - buf_priv->dispatched = 0; - buf_priv->list_entry = entry; + start = dev_priv->last_buf; - dev_priv->head->next = entry; + for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { + u32 done_age = GET_SCRATCH( 1 ); + DRM_DEBUG("done_age = %d\n",done_age); + for ( i = start ; i < dma->buf_count ; i++ ) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if ( buf->pid == 0 || (buf->pending && + buf_priv->age <= done_age) ) { + dev_priv->stats.requested_bufs++; + buf->pending = 0; + return buf; + } + start = 0; + } - if ( dev_priv->head->next ) - dev_priv->head->next->prev = entry; + if (t) { + DRM_UDELAY( 1 ); + dev_priv->stats.freelist_loops++; + } } - return 0; - + DRM_DEBUG( "returning NULL!\n" ); + return NULL; } -#endif - +#if 0 drm_buf_t *radeon_freelist_get( drm_device_t *dev ) { drm_device_dma_t *dma = dev->dma; @@ -1285,76 +1544,40 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev ) 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 ); - } + u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)); -#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 + dev_priv->stats.freelist_loops++; + + for ( t = 0 ; t < 2 ; t++ ) { 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. - */ + if ( buf->pid == 0 || (buf->pending && + buf_priv->age <= done_age) ) { + dev_priv->stats.requested_bufs++; 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 ); + start = 0; } - DRM_ERROR( "returning NULL!\n" ); return NULL; } +#endif 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; @@ -1371,12 +1594,24 @@ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n ) { drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; + u32 last_head = GET_RING_HEAD(ring); for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - radeon_update_ring_snapshot( ring ); + u32 head = GET_RING_HEAD(ring); + + ring->space = (head - ring->tail) * sizeof(u32); + if ( ring->space <= 0 ) + ring->space += ring->size; if ( ring->space > n ) return 0; - DRM_OS_DELAY( 1 ); + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + if (head != last_head) + i = 0; + last_head = head; + + DRM_UDELAY( 1 ); } /* FIXME: This return value is ignored in the BEGIN_RING macro! */ @@ -1384,7 +1619,7 @@ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n ) radeon_status( dev_priv ); DRM_ERROR( "failed!\n" ); #endif - return DRM_OS_ERR(EBUSY); + return DRM_ERR(EBUSY); } static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d ) @@ -1394,47 +1629,47 @@ static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d ) for ( i = d->granted_count ; i < d->request_count ; i++ ) { buf = radeon_freelist_get( dev ); - if ( !buf ) return DRM_OS_ERR(EAGAIN); + if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */ - buf->pid = DRM_OS_CURRENTPID; + buf->pid = DRM_CURRENTPID; - if (DRM_OS_COPYTOUSR( &d->request_indices[i], &buf->idx, + if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx, sizeof(buf->idx) ) ) - return DRM_OS_ERR(EFAULT); - if (DRM_OS_COPYTOUSR( &d->request_sizes[i], &buf->total, + return DRM_ERR(EFAULT); + if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total, sizeof(buf->total) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); d->granted_count++; } return 0; } -int radeon_cp_buffers( DRM_OS_IOCTL ) +int radeon_cp_buffers( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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) ); + DRM_COPY_FROM_USER_IOCTL( 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 ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, d.send_count ); + return DRM_ERR(EINVAL); } /* We'll send you buffers. */ if ( d.request_count < 0 || d.request_count > dma->buf_count ) { DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n", - DRM_OS_CURRENTPID, d.request_count, dma->buf_count ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, d.request_count, dma->buf_count ); + return DRM_ERR(EINVAL); } d.granted_count = 0; @@ -1443,7 +1678,7 @@ int radeon_cp_buffers( DRM_OS_IOCTL ) ret = radeon_cp_get_buffers( dev, &d ); } - DRM_OS_KRNTOUSR( (drm_dma_t *) data, d, sizeof(d) ); + DRM_COPY_TO_USER_IOCTL( (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 index 14b64e5..2c3cff0 100644 --- a/sys/dev/drm/radeon_drm.h +++ b/sys/dev/drm/radeon_drm.h @@ -2,6 +2,7 @@ * * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -26,6 +27,7 @@ * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * * $FreeBSD$ */ @@ -39,7 +41,8 @@ #ifndef __RADEON_SAREA_DEFINES__ #define __RADEON_SAREA_DEFINES__ -/* What needs to be changed for the current vertex buffer? +/* Old style state flags, required for sarea interface (1.1 and 1.2 + * clears) and 1.2 drm_vertex2 ioctl. */ #define RADEON_UPLOAD_CONTEXT 0x00000001 #define RADEON_UPLOAD_VERTFMT 0x00000002 @@ -58,11 +61,136 @@ #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_UPLOAD_ZBIAS 0x00020000 /* version 1.2 and newer */ +#define RADEON_UPLOAD_ALL 0x003effff +#define RADEON_UPLOAD_CONTEXT_ALL 0x003e01ff + + +/* New style per-packet identifiers for use in cmd_buffer ioctl with + * the RADEON_EMIT_PACKET command. Comments relate new packets to old + * state bits and the packet size: + */ +#define RADEON_EMIT_PP_MISC 0 /* context/7 */ +#define RADEON_EMIT_PP_CNTL 1 /* context/3 */ +#define RADEON_EMIT_RB3D_COLORPITCH 2 /* context/1 */ +#define RADEON_EMIT_RE_LINE_PATTERN 3 /* line/2 */ +#define RADEON_EMIT_SE_LINE_WIDTH 4 /* line/1 */ +#define RADEON_EMIT_PP_LUM_MATRIX 5 /* bumpmap/1 */ +#define RADEON_EMIT_PP_ROT_MATRIX_0 6 /* bumpmap/2 */ +#define RADEON_EMIT_RB3D_STENCILREFMASK 7 /* masks/3 */ +#define RADEON_EMIT_SE_VPORT_XSCALE 8 /* viewport/6 */ +#define RADEON_EMIT_SE_CNTL 9 /* setup/2 */ +#define RADEON_EMIT_SE_CNTL_STATUS 10 /* setup/1 */ +#define RADEON_EMIT_RE_MISC 11 /* misc/1 */ +#define RADEON_EMIT_PP_TXFILTER_0 12 /* tex0/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_0 13 /* tex0/1 */ +#define RADEON_EMIT_PP_TXFILTER_1 14 /* tex1/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_1 15 /* tex1/1 */ +#define RADEON_EMIT_PP_TXFILTER_2 16 /* tex2/6 */ +#define RADEON_EMIT_PP_BORDER_COLOR_2 17 /* tex2/1 */ +#define RADEON_EMIT_SE_ZBIAS_FACTOR 18 /* zbias/2 */ +#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT 19 /* tcl/11 */ +#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED 20 /* material/17 */ +#define R200_EMIT_PP_TXCBLEND_0 21 /* tex0/4 */ +#define R200_EMIT_PP_TXCBLEND_1 22 /* tex1/4 */ +#define R200_EMIT_PP_TXCBLEND_2 23 /* tex2/4 */ +#define R200_EMIT_PP_TXCBLEND_3 24 /* tex3/4 */ +#define R200_EMIT_PP_TXCBLEND_4 25 /* tex4/4 */ +#define R200_EMIT_PP_TXCBLEND_5 26 /* tex5/4 */ +#define R200_EMIT_PP_TXCBLEND_6 27 /* /4 */ +#define R200_EMIT_PP_TXCBLEND_7 28 /* /4 */ +#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0 29 /* tcl/7 */ +#define R200_EMIT_TFACTOR_0 30 /* tf/7 */ +#define R200_EMIT_VTX_FMT_0 31 /* vtx/5 */ +#define R200_EMIT_VAP_CTL 32 /* vap/1 */ +#define R200_EMIT_MATRIX_SELECT_0 33 /* msl/5 */ +#define R200_EMIT_TEX_PROC_CTL_2 34 /* tcg/5 */ +#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL 35 /* tcl/1 */ +#define R200_EMIT_PP_TXFILTER_0 36 /* tex0/6 */ +#define R200_EMIT_PP_TXFILTER_1 37 /* tex1/6 */ +#define R200_EMIT_PP_TXFILTER_2 38 /* tex2/6 */ +#define R200_EMIT_PP_TXFILTER_3 39 /* tex3/6 */ +#define R200_EMIT_PP_TXFILTER_4 40 /* tex4/6 */ +#define R200_EMIT_PP_TXFILTER_5 41 /* tex5/6 */ +#define R200_EMIT_PP_TXOFFSET_0 42 /* tex0/1 */ +#define R200_EMIT_PP_TXOFFSET_1 43 /* tex1/1 */ +#define R200_EMIT_PP_TXOFFSET_2 44 /* tex2/1 */ +#define R200_EMIT_PP_TXOFFSET_3 45 /* tex3/1 */ +#define R200_EMIT_PP_TXOFFSET_4 46 /* tex4/1 */ +#define R200_EMIT_PP_TXOFFSET_5 47 /* tex5/1 */ +#define R200_EMIT_VTE_CNTL 48 /* vte/1 */ +#define R200_EMIT_OUTPUT_VTX_COMP_SEL 49 /* vtx/1 */ +#define R200_EMIT_PP_TAM_DEBUG3 50 /* tam/1 */ +#define R200_EMIT_PP_CNTL_X 51 /* cst/1 */ +#define R200_EMIT_RB3D_DEPTHXY_OFFSET 52 /* cst/1 */ +#define R200_EMIT_RE_AUX_SCISSOR_CNTL 53 /* cst/1 */ +#define R200_EMIT_RE_SCISSOR_TL_0 54 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_1 55 /* cst/2 */ +#define R200_EMIT_RE_SCISSOR_TL_2 56 /* cst/2 */ +#define R200_EMIT_SE_VAP_CNTL_STATUS 57 /* cst/1 */ +#define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */ +#define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */ +#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */ +#define R200_EMIT_PP_CUBIC_FACES_0 61 +#define R200_EMIT_PP_CUBIC_OFFSETS_0 62 +#define R200_EMIT_PP_CUBIC_FACES_1 63 +#define R200_EMIT_PP_CUBIC_OFFSETS_1 64 +#define R200_EMIT_PP_CUBIC_FACES_2 65 +#define R200_EMIT_PP_CUBIC_OFFSETS_2 66 +#define R200_EMIT_PP_CUBIC_FACES_3 67 +#define R200_EMIT_PP_CUBIC_OFFSETS_3 68 +#define R200_EMIT_PP_CUBIC_FACES_4 69 +#define R200_EMIT_PP_CUBIC_OFFSETS_4 70 +#define R200_EMIT_PP_CUBIC_FACES_5 71 +#define R200_EMIT_PP_CUBIC_OFFSETS_5 72 +#define RADEON_MAX_STATE_PACKETS 73 + + +/* Commands understood by cmd_buffer ioctl. More can be added but + * obviously these can't be removed or changed: + */ +#define RADEON_CMD_PACKET 1 /* emit one of the register packets above */ +#define RADEON_CMD_SCALARS 2 /* emit scalar data */ +#define RADEON_CMD_VECTORS 3 /* emit vector data */ +#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */ +#define RADEON_CMD_PACKET3 5 /* emit hw packet */ +#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */ +#define RADEON_CMD_SCALARS2 7 /* r200 stopgap */ +#define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: + * doesn't make the cpu wait, just + * the graphics hardware */ + + +typedef union { + int i; + struct { + unsigned char cmd_type, pad0, pad1, pad2; + } header; + struct { + unsigned char cmd_type, packet_id, pad0, pad1; + } packet; + struct { + unsigned char cmd_type, offset, stride, count; + } scalars; + struct { + unsigned char cmd_type, offset, stride, count; + } vectors; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; + } dma; + struct { + unsigned char cmd_type, flags, pad0, pad1; + } wait; +} drm_radeon_cmd_header_t; + +#define RADEON_WAIT_2D 0x1 +#define RADEON_WAIT_3D 0x2 + #define RADEON_FRONT 0x1 #define RADEON_BACK 0x2 #define RADEON_DEPTH 0x4 +#define RADEON_STENCIL 0x8 /* Primitive types */ @@ -80,12 +208,9 @@ /* 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 @@ -97,7 +222,7 @@ #define RADEON_NR_TEX_REGIONS 64 #define RADEON_LOG_TEX_GRANULARITY 16 -#define RADEON_MAX_TEXTURE_LEVELS 11 +#define RADEON_MAX_TEXTURE_LEVELS 12 #define RADEON_MAX_TEXTURE_UNITS 3 #endif /* __RADEON_SAREA_DEFINES__ */ @@ -157,28 +282,18 @@ typedef struct { /* 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; +typedef struct { + /* Zbias state */ + unsigned int se_zbias_factor; /* 0x1dac */ + unsigned int se_zbias_constant; +} drm_radeon_context2_regs_t; + + /* Setup registers for each texture unit */ typedef struct { @@ -188,24 +303,37 @@ typedef struct { 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 int start; + unsigned int finish; + unsigned int prim:8; + unsigned int stateidx:8; + unsigned int numverts:16; /* overloaded as offset/64 for elt prims */ + unsigned int vc_format; /* vertex format */ +} drm_radeon_prim_t; + + +typedef struct { + drm_radeon_context_regs_t context; + drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS]; + drm_radeon_context2_regs_t context2; + unsigned int dirty; +} drm_radeon_state_t; + + +typedef struct { 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. + /* The channel for communication of state information to the + * kernel on firing a vertex buffer with either of the + * obsoleted vertex/index ioctls. */ drm_radeon_context_regs_t context_state; drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS]; @@ -227,33 +355,50 @@ typedef struct { 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; + int pfState; /* number of 3d windows (0,1,2ormore) */ + int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ } drm_radeon_sarea_t; /* WARNING: If you change any of these defines, make sure to change the * defines in the Xserver file (xf86drmRadeon.h) + * + * KW: actually it's illegal to change any of this (backwards compatibility). */ -/* Radeon specific ioctls */ -#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) +/* Radeon specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#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) +#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex2_t) +#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t) +#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t) +#define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52) +#define DRM_IOCTL_RADEON_ALLOC DRM_IOWR( 0x53, drm_radeon_mem_alloc_t) +#define DRM_IOCTL_RADEON_FREE DRM_IOW( 0x54, drm_radeon_mem_free_t) +#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t) +#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t) +#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t) typedef struct drm_radeon_init { enum { RADEON_INIT_CP = 0x01, - RADEON_CLEANUP_CP = 0x02 + RADEON_CLEANUP_CP = 0x02, + RADEON_INIT_R200_CP = 0x03 } func; unsigned long sarea_priv_offset; int is_pci; @@ -304,7 +449,7 @@ typedef struct drm_radeon_clear { unsigned int clear_color; unsigned int clear_depth; unsigned int color_mask; - unsigned int depth_mask; + unsigned int depth_mask; /* misnamed field: should be stencil */ drm_radeon_clear_rect_t *depth_boxes; } drm_radeon_clear_t; @@ -323,6 +468,36 @@ typedef struct drm_radeon_indices { int discard; /* Client finished with buffer? */ } drm_radeon_indices_t; +/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices + * - allows multiple primitives and state changes in a single ioctl + * - supports driver change to emit native primitives + */ +typedef struct drm_radeon_vertex2 { + int idx; /* Index of vertex buffer */ + int discard; /* Client finished with buffer? */ + int nr_states; + drm_radeon_state_t *state; + int nr_prims; + drm_radeon_prim_t *prim; +} drm_radeon_vertex2_t; + +/* v1.3 - obsoletes drm_radeon_vertex2 + * - allows arbitarily large cliprect list + * - allows updating of tcl packet, vector and scalar state + * - allows memory-efficient description of state updates + * - allows state to be emitted without a primitive + * (for clears, ctx switches) + * - allows more than one dma buffer to be referenced per ioctl + * - supports tcl driver + * - may be extended in future versions with new cmd types, packets + */ +typedef struct drm_radeon_cmd_buffer { + int bufsz; + char *buf; + int nbox; + drm_clip_rect_t *boxes; +} drm_radeon_cmd_buffer_t; + typedef struct drm_radeon_tex_image { unsigned int x, y; /* Blit coordinates */ unsigned int width, height; @@ -349,4 +524,55 @@ typedef struct drm_radeon_indirect { int discard; } drm_radeon_indirect_t; + +/* 1.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define RADEON_PARAM_AGP_BUFFER_OFFSET 1 /* card offset of 1st agp buffer */ +#define RADEON_PARAM_LAST_FRAME 2 +#define RADEON_PARAM_LAST_DISPATCH 3 +#define RADEON_PARAM_LAST_CLEAR 4 +#define RADEON_PARAM_IRQ_NR 5 +#define RADEON_PARAM_AGP_BASE 6 /* card offset of agp base */ + +typedef struct drm_radeon_getparam { + int param; + int *value; +} drm_radeon_getparam_t; + +/* 1.6: Set up a memory manager for regions of shared memory: + */ +#define RADEON_MEM_REGION_AGP 1 +#define RADEON_MEM_REGION_FB 2 + +typedef struct drm_radeon_mem_alloc { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drm_radeon_mem_alloc_t; + +typedef struct drm_radeon_mem_free { + int region; + int region_offset; +} drm_radeon_mem_free_t; + +typedef struct drm_radeon_mem_init_heap { + int region; + int size; + int start; +} drm_radeon_mem_init_heap_t; + + +/* 1.6: Userspace can request & wait on irq's: + */ +typedef struct drm_radeon_irq_emit { + int *irq_seq; +} drm_radeon_irq_emit_t; + +typedef struct drm_radeon_irq_wait { + int irq_seq; +} drm_radeon_irq_wait_t; + + #endif diff --git a/sys/dev/drm/radeon_drv.c b/sys/dev/drm/radeon_drv.c index 25f6f2f..b00eef6 100644 --- a/sys/dev/drm/radeon_drv.c +++ b/sys/dev/drm/radeon_drv.c @@ -29,90 +29,51 @@ * $FreeBSD$ */ - -#ifdef __linux__ -#include <linux/config.h> -#endif /* __linux__ */ - -#ifdef __FreeBSD__ -#include <sys/types.h> -#include <sys/bus.h> -#include <pci/pcivar.h> -#endif /* __FreeBSD__ */ - #include "dev/drm/radeon.h" #include "dev/drm/drmP.h" +#include "dev/drm/drm.h" #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" #if __REALLY_HAVE_SG -#include "ati_pcigart.h" +#include "dev/drm/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, 0x4242, 1, "ATI Radeon BB AIW 8500DV (AGP)"}, + {0x1002, 0x4336, 1, "ATI Radeon Mobility"}, + {0x1002, 0x4337, 1, "ATI Radeon IGP 340"}, + {0x1002, 0x4964, 1, "ATI Radeon Id 9000"}, + {0x1002, 0x4965, 1, "ATI Radeon Ie 9000"}, + {0x1002, 0x4966, 1, "ATI Radeon If 9000"}, + {0x1002, 0x4967, 1, "ATI Radeon Ig 9000"}, + {0x1002, 0x496e, 1, "ATI Radeon Ig 9000"}, {0x1002, 0x4C57, 1, "ATI Radeon LW Mobility 7 (AGP)"}, + {0x1002, 0x4C58, 1, "ATI Radeon LX 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, 0x4C64, 1, "ATI Radeon Ld Mobility 9000 (AGP)"}, + {0x1002, 0x4C65, 1, "ATI Radeon Le Mobility 9000 (AGP)"}, + {0x1002, 0x4C66, 1, "ATI Radeon Lf Mobility 9000 (AGP)"}, + {0x1002, 0x4C67, 1, "ATI Radeon Lg Mobility 9000 (AGP)"}, + {0x1002, 0x5144, 1, "ATI Radeon QD R100 (AGP)"}, + {0x1002, 0x5145, 1, "ATI Radeon QE R100 (AGP)"}, + {0x1002, 0x5146, 1, "ATI Radeon QF R100 (AGP)"}, + {0x1002, 0x5147, 1, "ATI Radeon QG R100 (AGP)"}, + {0x1002, 0x5148, 1, "ATI Radeon QH FireGL 8x00 (AGP)"}, + {0x1002, 0x5149, 1, "ATI Radeon QI R200"}, + {0x1002, 0x514A, 1, "ATI Radeon QJ R200"}, + {0x1002, 0x514B, 1, "ATI Radeon QK R200"}, + {0x1002, 0x514C, 1, "ATI Radeon QL 8500 (AGP)"}, {0x1002, 0x5157, 1, "ATI Radeon QW 7500 (AGP)"}, + {0x1002, 0x5158, 1, "ATI Radeon QX 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)"}, + {0x1002, 0x5168, 1, "ATI Radeon Qh R200"}, + {0x1002, 0x5169, 1, "ATI Radeon Qi R200"}, + {0x1002, 0x516A, 1, "ATI Radeon Qj R200"}, + {0x1002, 0x516B, 1, "ATI Radeon Qk R200"}, {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" @@ -121,45 +82,19 @@ drm_chipinfo_t DRM(devicelist)[] = { #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 +#if __HAVE_SG #include "dev/drm/drm_scatter.h" #endif #ifdef __FreeBSD__ -DRIVER_MODULE(radeon, pci, radeon_driver, radeon_devclass, 0, 0); +DRIVER_MODULE(DRIVER_NAME, pci, DRM(driver), DRM(devclass), 0, 0); +#elif defined(__NetBSD__) +CFDRIVER_DECL(radeon, DV_TTY, NULL); #endif /* __FreeBSD__ */ diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h index 731c093..4288970 100644 --- a/sys/dev/drm/radeon_drv.h +++ b/sys/dev/drm/radeon_drv.h @@ -33,6 +33,9 @@ #ifndef __RADEON_DRV_H__ #define __RADEON_DRV_H__ +#define GET_RING_HEAD(ring) DRM_READ32( (ring)->ring_rptr, 0 ) /* (ring)->head */ +#define SET_RING_HEAD(ring,val) DRM_WRITE32( (ring)->ring_rptr, 0, (val) ) /* (ring)->head */ + typedef struct drm_radeon_freelist { unsigned int age; drm_buf_t *buf; @@ -52,6 +55,7 @@ typedef struct drm_radeon_ring_buffer { int space; int high_mark; + drm_local_map_t *ring_rptr; } drm_radeon_ring_buffer_t; typedef struct drm_radeon_depth_clear_t { @@ -60,6 +64,15 @@ typedef struct drm_radeon_depth_clear_t { u32 se_cntl; } drm_radeon_depth_clear_t; + +struct mem_block { + struct mem_block *next; + struct mem_block *prev; + int start; + int size; + int pid; /* 0: free, -1: heap, other: real pids */ +}; + typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; @@ -73,29 +86,32 @@ typedef struct drm_radeon_private { 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 writeback_works; int usec_timeout; + + int is_r200; + int is_pci; unsigned long phys_pci_gart; -#if __REALLY_HAVE_SG dma_addr_t bus_pci_gart; -#endif - - atomic_t idle_count; + struct { + u32 boxes; + int freelist_timeouts; + int freelist_loops; + int requested_bufs; + int last_frame_reads; + int last_clear_reads; + int clears; + int texture_uploads; + } stats; + + int do_boxes; int page_flipping; int current_page; - u32 crtc_offset; - u32 crtc_offset_cntl; u32 color_fmt; unsigned int front_offset; @@ -113,58 +129,84 @@ typedef struct drm_radeon_private { 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_local_map_t *sarea; + drm_local_map_t *fb; + drm_local_map_t *mmio; + drm_local_map_t *cp_ring; + drm_local_map_t *ring_rptr; + drm_local_map_t *buffers; + drm_local_map_t *agp_textures; + + struct mem_block *agp_heap; + struct mem_block *fb_heap; + + /* SW interrupt */ + wait_queue_head_t swi_queue; + atomic_t swi_emitted; + } 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 int radeon_cp_init( DRM_IOCTL_ARGS ); +extern int radeon_cp_start( DRM_IOCTL_ARGS ); +extern int radeon_cp_stop( DRM_IOCTL_ARGS ); +extern int radeon_cp_reset( DRM_IOCTL_ARGS ); +extern int radeon_cp_idle( DRM_IOCTL_ARGS ); +extern int radeon_engine_reset( DRM_IOCTL_ARGS ); +extern int radeon_fullscreen( DRM_IOCTL_ARGS ); +extern int radeon_cp_buffers( DRM_IOCTL_ARGS ); 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 ); +extern int radeon_cp_clear( DRM_IOCTL_ARGS ); +extern int radeon_cp_swap( DRM_IOCTL_ARGS ); +extern int radeon_cp_vertex( DRM_IOCTL_ARGS ); +extern int radeon_cp_indices( DRM_IOCTL_ARGS ); +extern int radeon_cp_texture( DRM_IOCTL_ARGS ); +extern int radeon_cp_stipple( DRM_IOCTL_ARGS ); +extern int radeon_cp_indirect( DRM_IOCTL_ARGS ); +extern int radeon_cp_vertex2( DRM_IOCTL_ARGS ); +extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ); +extern int radeon_cp_getparam( DRM_IOCTL_ARGS ); +extern int radeon_cp_flip( DRM_IOCTL_ARGS ); + +extern int radeon_mem_alloc( DRM_IOCTL_ARGS ); +extern int radeon_mem_free( DRM_IOCTL_ARGS ); +extern int radeon_mem_init_heap( DRM_IOCTL_ARGS ); +extern void radeon_mem_takedown( struct mem_block **heap ); +extern void radeon_mem_release( struct mem_block *heap ); + + /* radeon_irq.c */ +extern int radeon_irq_emit( DRM_IOCTL_ARGS ); +extern int radeon_irq_wait( DRM_IOCTL_ARGS ); + +extern int radeon_emit_and_wait_irq(drm_device_t *dev); +extern int radeon_wait_irq(drm_device_t *dev, int swi_nr); +extern int radeon_emit_irq(drm_device_t *dev); + +extern void radeon_do_release(drm_device_t *dev); + +/* Flags for stats.boxes + */ +#define RADEON_BOX_DMA_IDLE 0x1 +#define RADEON_BOX_RING_FULL 0x2 +#define RADEON_BOX_FLIP 0x4 +#define RADEON_BOX_WAIT_IDLE 0x8 +#define RADEON_BOX_TEXTURE_LOAD 0x10 + + /* Register definitions, register access macros and drmAddMap constants * for Radeon kernel driver. @@ -190,10 +232,10 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #define RADEON_CRTC_OFFSET_CNTL 0x0228 # define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +#define RADEON_CRTC2_OFFSET 0x0324 +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 #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) @@ -228,6 +270,26 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #define RADEON_SCRATCH_UMSK 0x0770 #define RADEON_SCRATCH_ADDR 0x0774 +#define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x)) + +#define GET_SCRATCH( x ) (dev_priv->writeback_works \ + ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \ + : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) + + +#define RADEON_GEN_INT_CNTL 0x0040 +# define RADEON_CRTC_VBLANK_MASK (1 << 0) +# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) +# define RADEON_SW_INT_ENABLE (1 << 25) + +#define RADEON_GEN_INT_STATUS 0x0044 +# define RADEON_CRTC_VBLANK_STAT (1 << 0) +# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) +# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19) +# define RADEON_SW_INT_TEST (1 << 25) +# define RADEON_SW_INT_TEST_ACK (1 << 25) +# define RADEON_SW_INT_FIRE (1 << 26) + #define RADEON_HOST_PATH_CNTL 0x0130 # define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) @@ -241,6 +303,12 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); # define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4) # define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5) +#define RADEON_RBBM_GUICNTL 0x172c +# define RADEON_HOST_DATA_SWAP_NONE (0 << 0) +# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) +# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) +# define RADEON_HOST_DATA_SWAP_HDW (3 << 0) + #define RADEON_MC_AGP_LOCATION 0x014c #define RADEON_MC_FB_LOCATION 0x0148 #define RADEON_MCLK_CNTL 0x0012 @@ -278,10 +346,8 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); # 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_DEPTHPITCH 0x1c28 #define RADEON_RB3D_PLANEMASK 0x1d84 #define RADEON_RB3D_STENCILREFMASK 0x1d7c #define RADEON_RB3D_ZCACHE_MODE 0x3250 @@ -294,9 +360,9 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); # 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_STENCIL_S_FAIL_REPLACE (2 << 16) +# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) +# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) # define RADEON_Z_WRITE_ENABLE (1 << 30) #define RADEON_RBBM_SOFT_RESET 0x00f0 # define RADEON_SOFT_RESET_CP (1 << 0) @@ -345,6 +411,16 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #define RADEON_SE_CNTL_STATUS 0x2140 #define RADEON_SE_LINE_WIDTH 0x1db8 #define RADEON_SE_VPORT_XSCALE 0x1d98 +#define RADEON_SE_ZBIAS_FACTOR 0x1db0 +#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 +#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 +#define RADEON_SE_TCL_VECTOR_INDX_REG 0x2200 +# define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16 +# define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28 +#define RADEON_SE_TCL_VECTOR_DATA_REG 0x2204 +#define RADEON_SE_TCL_SCALAR_INDX_REG 0x2208 +# define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16 +#define RADEON_SE_TCL_SCALAR_DATA_REG 0x220C #define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8 #define RADEON_SURFACE_ACCESS_CLR 0x0bfc #define RADEON_SURFACE_CNTL 0x0b00 @@ -409,6 +485,7 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #define RADEON_CP_RB_BASE 0x0700 #define RADEON_CP_RB_CNTL 0x0704 +# define RADEON_BUF_SWAP_32BIT (2 << 16) #define RADEON_CP_RB_RPTR_ADDR 0x070c #define RADEON_CP_RB_RPTR 0x0710 #define RADEON_CP_RB_WPTR 0x0714 @@ -445,11 +522,14 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #define RADEON_CP_PACKET3 0xC0000000 # define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300 # define RADEON_WAIT_FOR_IDLE 0x00002600 +# define RADEON_3D_DRAW_VBUF 0x00002800 # define RADEON_3D_DRAW_IMMD 0x00002900 -# define RADEON_3D_CLEAR_ZMASK 0x00003200 +# define RADEON_3D_DRAW_INDX 0x00002A00 +# define RADEON_3D_LOAD_VBPNTR 0x00002F00 # define RADEON_CNTL_HOSTDATA_BLT 0x00009400 # define RADEON_CNTL_PAINT_MULTI 0x00009A00 # define RADEON_CNTL_BITBLT_MULTI 0x00009B00 +# define RADEON_CNTL_SET_SCISSORS 0xC0001E00 #define RADEON_CP_PACKET_MASK 0xC0000000 #define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 @@ -458,6 +538,7 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 #define RADEON_VTX_Z_PRESENT (1 << 31) +#define RADEON_VTX_PKCOLOR_PRESENT (1 << 3) #define RADEON_PRIM_TYPE_NONE (0 << 0) #define RADEON_PRIM_TYPE_POINT (1 << 0) @@ -470,6 +551,7 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #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_TYPE_MASK 0xf #define RADEON_PRIM_WALK_IND (1 << 4) #define RADEON_PRIM_WALK_LIST (2 << 4) #define RADEON_PRIM_WALK_RING (3 << 4) @@ -496,6 +578,105 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #define RADEON_TXFORMAT_ARGB4444 5 #define RADEON_TXFORMAT_ARGB8888 6 #define RADEON_TXFORMAT_RGBA8888 7 +#define RADEON_TXFORMAT_VYUY422 10 +#define RADEON_TXFORMAT_YVYU422 11 +#define RADEON_TXFORMAT_DXT1 12 +#define RADEON_TXFORMAT_DXT23 14 +#define RADEON_TXFORMAT_DXT45 15 + +#define R200_PP_TXCBLEND_0 0x2f00 +#define R200_PP_TXCBLEND_1 0x2f10 +#define R200_PP_TXCBLEND_2 0x2f20 +#define R200_PP_TXCBLEND_3 0x2f30 +#define R200_PP_TXCBLEND_4 0x2f40 +#define R200_PP_TXCBLEND_5 0x2f50 +#define R200_PP_TXCBLEND_6 0x2f60 +#define R200_PP_TXCBLEND_7 0x2f70 +#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268 +#define R200_PP_TFACTOR_0 0x2ee0 +#define R200_SE_VTX_FMT_0 0x2088 +#define R200_SE_VAP_CNTL 0x2080 +#define R200_SE_TCL_MATRIX_SEL_0 0x2230 +#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8 +#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0 +#define R200_PP_TXFILTER_5 0x2ca0 +#define R200_PP_TXFILTER_4 0x2c80 +#define R200_PP_TXFILTER_3 0x2c60 +#define R200_PP_TXFILTER_2 0x2c40 +#define R200_PP_TXFILTER_1 0x2c20 +#define R200_PP_TXFILTER_0 0x2c00 +#define R200_PP_TXOFFSET_5 0x2d78 +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_TXOFFSET_0 0x2d00 + +#define R200_PP_CUBIC_FACES_0 0x2c18 +#define R200_PP_CUBIC_FACES_1 0x2c38 +#define R200_PP_CUBIC_FACES_2 0x2c58 +#define R200_PP_CUBIC_FACES_3 0x2c78 +#define R200_PP_CUBIC_FACES_4 0x2c98 +#define R200_PP_CUBIC_FACES_5 0x2cb8 +#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 +#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 +#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c +#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 +#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 +#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c +#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 +#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 +#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 +#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c +#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 +#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 +#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c +#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 +#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 +#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c +#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 +#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 +#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 +#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c +#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 +#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 +#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c +#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 +#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 +#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c +#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 +#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 +#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 +#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c + +#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 +#define R200_SE_VTE_CNTL 0x20b0 +#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 +#define R200_PP_TAM_DEBUG3 0x2d9c +#define R200_PP_CNTL_X 0x2cc4 +#define R200_SE_VAP_CNTL_STATUS 0x2140 +#define R200_RE_SCISSOR_TL_0 0x1cd8 +#define R200_RE_SCISSOR_TL_1 0x1ce0 +#define R200_RE_SCISSOR_TL_2 0x1ce8 +#define R200_RB3D_DEPTHXY_OFFSET 0x1d60 +#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 +#define R200_SE_VTX_STATE_CNTL 0x2180 +#define R200_RE_POINTSIZE 0x2648 +#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 + + +#define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 +#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 +#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012 +#define SE_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100 +#define SE_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200 +#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK 0x00000001 +#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK 0x00000002 +#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b +#define R200_3D_DRAW_IMMD_2 0xC0003500 +#define R200_SE_VTX_FMT_1 0x208c +#define R200_RE_CNTL 0x1c50 + /* Constants */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ @@ -503,6 +684,7 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #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_SWI_REG RADEON_SCRATCH_REG3 #define RADEON_LAST_DISPATCH 1 #define RADEON_MAX_VB_AGE 0x7fffffff @@ -510,45 +692,10 @@ extern int radeon_cp_indirect( DRM_OS_IOCTL ); #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_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) +#define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) +#define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) +#define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) #define RADEON_WRITE_PLL( addr, val ) \ do { \ @@ -628,42 +775,24 @@ extern int RADEON_READ_PLL( drm_device_t *dev, int addr ); #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", __func__ ); \ - return DRM_OS_ERR(EINVAL); \ + dev->lock.pid != DRM_CURRENTPID ) { \ + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); \ + return DRM_ERR(EINVAL); \ } \ } while (0) + +/* Perfbox functionality only. + */ #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" ); \ - return DRM_OS_ERR(EBUSY); \ + if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) { \ + u32 head = GET_RING_HEAD(&dev_priv->ring); \ + if (head == dev_priv->ring.tail) \ + dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE; \ } \ - __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; \ @@ -674,7 +803,6 @@ do { \ radeon_freelist_reset( dev ); \ } \ } while (0) -#endif /* __FreeBSD__ */ #define RADEON_DISPATCH_AGE( age ) do { \ OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \ @@ -696,22 +824,20 @@ do { \ * 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 RING_LOCALS int write, _nr; unsigned int mask; u32 *ring; #define BEGIN_RING( n ) do { \ if ( RADEON_VERBOSE ) { \ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ - n, __func__ ); \ + n, __FUNCTION__ ); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ + COMMIT_RING(); \ radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \ } \ - dev_priv->ring.space -= (n) * sizeof(u32); \ + _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ mask = dev_priv->ring.tail_mask; \ @@ -722,9 +848,22 @@ do { \ 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 ); \ + if (((dev_priv->ring.tail + _nr) & mask) != write) { \ + DRM_ERROR( \ + "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ + ((dev_priv->ring.tail + _nr) & mask), \ + write, __LINE__); \ + } else \ + dev_priv->ring.tail = write; \ +} while (0) + +#define COMMIT_RING() do { \ + /* Flush writes to ring */ \ + DRM_READMEMORYBARRIER(dev_priv->mmio); \ + GET_RING_HEAD( &dev_priv->ring ); \ + RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \ + /* read from PCI bus to ensure correct posting */ \ + RADEON_READ( RADEON_CP_RB_RPTR ); \ } while (0) #define OUT_RING( x ) do { \ @@ -736,6 +875,33 @@ do { \ write &= mask; \ } while (0) -#define RADEON_PERFORMANCE_BOXES 0 +#define OUT_RING_REG( reg, val ) do { \ + OUT_RING( CP_PACKET0( reg, 0 ) ); \ + OUT_RING( val ); \ +} while (0) + + +#define OUT_RING_USER_TABLE( tab, sz ) do { \ + int _size = (sz); \ + int *_tab = (tab); \ + \ + if (write + _size > mask) { \ + int i = (mask+1) - write; \ + if (DRM_COPY_FROM_USER_UNCHECKED( (int *)(ring+write), \ + _tab, i*4 )) \ + return DRM_ERR(EFAULT); \ + write = 0; \ + _size -= i; \ + _tab += i; \ + } \ + \ + if (_size && DRM_COPY_FROM_USER_UNCHECKED( (int *)(ring+write), \ + _tab, _size*4 )) \ + return DRM_ERR(EFAULT); \ + \ + write += _size; \ + write &= mask; \ +} while (0) + #endif /* __RADEON_DRV_H__ */ diff --git a/sys/dev/drm/radeon_irq.c b/sys/dev/drm/radeon_irq.c new file mode 100644 index 0000000..8661a58 --- /dev/null +++ b/sys/dev/drm/radeon_irq.c @@ -0,0 +1,258 @@ +/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Michel Dänzer <michel@daenzer.net> + * + * $FreeBSD$ + */ + +#include "dev/drm/radeon.h" +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/radeon_drm.h" +#include "dev/drm/radeon_drv.h" + +/* Interrupts - Used for device synchronization and flushing in the + * following circumstances: + * + * - Exclusive FB access with hw idle: + * - Wait for GUI Idle (?) interrupt, then do normal flush. + * + * - Frame throttling, NV_fence: + * - Drop marker irq's into command stream ahead of time. + * - Wait on irq's with lock *not held* + * - Check each for termination condition + * + * - Internally in cp_getbuffer, etc: + * - as above, but wait with lock held??? + * + * NOTE: These functions are misleadingly named -- the irq's aren't + * tied to dma at all, this is just a hangover from dri prehistory. + */ + +void DRM(dma_service)( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + u32 stat; + + /* Only consider the bits we're interested in - others could be used + * outside the DRM + */ + stat = RADEON_READ(RADEON_GEN_INT_STATUS) + & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); + if (!stat) + return; + + /* SW interrupt */ + if (stat & RADEON_SW_INT_TEST) { + DRM_WAKEUP( &dev_priv->swi_queue ); + } + + /* VBLANK interrupt */ + if (stat & RADEON_CRTC_VBLANK_STAT) { + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + DRM(vbl_send_signals)( dev ); + } + + /* Acknowledge interrupts we handle */ + RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); +} + +static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) +{ + u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ) + & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT); + if (tmp) + RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); +} + +int radeon_emit_irq(drm_device_t *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + unsigned int ret; + RING_LOCALS; + + atomic_inc(&dev_priv->swi_emitted); + ret = atomic_read(&dev_priv->swi_emitted); + + BEGIN_RING( 4 ); + OUT_RING_REG( RADEON_LAST_SWI_REG, ret ); + OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE ); + ADVANCE_RING(); + COMMIT_RING(); + + return ret; +} + + +int radeon_wait_irq(drm_device_t *dev, int swi_nr) +{ + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + int ret = 0; + + if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) + return 0; + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + /* This is a hack to work around mysterious freezes on certain + * systems: + */ + radeon_acknowledge_irqs( dev_priv ); + + DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, + RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr ); + + return ret; +} + +int radeon_emit_and_wait_irq(drm_device_t *dev) +{ + return radeon_wait_irq( dev, radeon_emit_irq(dev) ); +} + + +int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) +{ + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + unsigned int cur_vblank; + int ret = 0; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + radeon_acknowledge_irqs( dev_priv ); + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + - *sequence ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + + +/* Needs the lock as it touches the ring. + */ +int radeon_irq_emit( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_irq_emit_t emit; + int result; + + LOCK_TEST_WITH_RETURN( dev ); + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t *)data, + sizeof(emit) ); + + result = radeon_emit_irq( dev ); + + if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} + + +/* Doesn't need the hardware lock. + */ +int radeon_irq_wait( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_irq_wait_t irqwait; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t *)data, + sizeof(irqwait) ); + + return radeon_wait_irq( dev, irqwait.irq_seq ); +} + + +/* drm_dma.h hooks +*/ +void DRM(driver_irq_preinstall)( drm_device_t *dev ) { + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + + /* Clear bits if they're already high */ + radeon_acknowledge_irqs( dev_priv ); +} + +void DRM(driver_irq_postinstall)( drm_device_t *dev ) { + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + + atomic_set(&dev_priv->swi_emitted, 0); + DRM_INIT_WAITQUEUE( &dev_priv->swi_queue ); + + /* Turn on SW and VBL ints */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, + RADEON_CRTC_VBLANK_MASK | + RADEON_SW_INT_ENABLE ); +} + +void DRM(driver_irq_uninstall)( drm_device_t *dev ) { + drm_radeon_private_t *dev_priv = + (drm_radeon_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + } +} diff --git a/sys/dev/drm/radeon_mem.c b/sys/dev/drm/radeon_mem.c new file mode 100644 index 0000000..9f9e50e --- /dev/null +++ b/sys/dev/drm/radeon_mem.c @@ -0,0 +1,326 @@ +/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + * $FreeBSD$ + */ + +#include "dev/drm/radeon.h" +#include "dev/drm/drmP.h" +#include "dev/drm/drm.h" +#include "dev/drm/radeon_drm.h" +#include "dev/drm/radeon_drv.h" + +/* Very simple allocator for agp memory, working on a static range + * already mapped into each client's address space. + */ + +static struct mem_block *split_block(struct mem_block *p, int start, int size, + int pid ) +{ + /* Maybe cut off the start of an existing block */ + if (start > p->start) { + struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock)); + if (!newblock) + goto out; + newblock->start = start; + newblock->size = p->size - (start - p->start); + newblock->pid = 0; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size -= newblock->size; + p = newblock; + } + + /* Maybe cut off the end of an existing block */ + if (size < p->size) { + struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock)); + if (!newblock) + goto out; + newblock->start = start + size; + newblock->size = p->size - size; + newblock->pid = 0; + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + p->size = size; + } + + out: + /* Our block is in the middle */ + p->pid = pid; + return p; +} + +static struct mem_block *alloc_block( struct mem_block *heap, int size, + int align2, int pid ) +{ + struct mem_block *p; + int mask = (1 << align2)-1; + + for (p = heap->next ; p != heap ; p = p->next) { + int start = (p->start + mask) & ~mask; + if (p->pid == 0 && start + size <= p->start + p->size) + return split_block( p, start, size, pid ); + } + + return NULL; +} + +static struct mem_block *find_block( struct mem_block *heap, int start ) +{ + struct mem_block *p; + + for (p = heap->next ; p != heap ; p = p->next) + if (p->start == start) + return p; + + return NULL; +} + + +static void free_block( struct mem_block *p ) +{ + p->pid = 0; + + /* Assumes a single contiguous range. Needs a special pid in + * 'heap' to stop it being subsumed. + */ + if (p->next->pid == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + DRM_FREE(q, sizeof(*q)); + } + + if (p->prev->pid == 0) { + struct mem_block *q = p->prev; + q->size += p->size; + q->next = p->next; + q->next->prev = q; + DRM_FREE(p, sizeof(*q)); + } +} + +/* Initialize. How to check for an uninitialized heap? + */ +static int init_heap(struct mem_block **heap, int start, int size) +{ + struct mem_block *blocks = DRM_MALLOC(sizeof(*blocks)); + + if (!blocks) + return -ENOMEM; + + *heap = DRM_MALLOC(sizeof(**heap)); + if (!*heap) { + DRM_FREE( blocks, sizeof(*blocks) ); + return -ENOMEM; + } + + blocks->start = start; + blocks->size = size; + blocks->pid = 0; + blocks->next = blocks->prev = *heap; + + memset( *heap, 0, sizeof(**heap) ); + (*heap)->pid = -1; + (*heap)->next = (*heap)->prev = blocks; + return 0; +} + + +/* Free all blocks associated with the releasing pid. + */ +void radeon_mem_release( struct mem_block *heap ) +{ + int pid = DRM_CURRENTPID; + struct mem_block *p; + + if (!heap || !heap->next) + return; + + for (p = heap->next ; p != heap ; p = p->next) { + if (p->pid == pid) + p->pid = 0; + } + + /* Assumes a single contiguous range. Needs a special pid in + * 'heap' to stop it being subsumed. + */ + for (p = heap->next ; p != heap ; p = p->next) { + while (p->pid == 0 && p->next->pid == 0) { + struct mem_block *q = p->next; + p->size += q->size; + p->next = q->next; + p->next->prev = p; + DRM_FREE(q, sizeof(*q)); + } + } +} + +/* Shutdown. + */ +void radeon_mem_takedown( struct mem_block **heap ) +{ + struct mem_block *p; + + if (!*heap) + return; + + for (p = (*heap)->next ; p != *heap ; ) { + struct mem_block *q = p; + p = p->next; + DRM_FREE(q, sizeof(*q)); + } + + DRM_FREE( *heap, sizeof(**heap) ); + *heap = 0; +} + + + +/* IOCTL HANDLERS */ + +static struct mem_block **get_heap( drm_radeon_private_t *dev_priv, + int region ) +{ + switch( region ) { + case RADEON_MEM_REGION_AGP: + return &dev_priv->agp_heap; + case RADEON_MEM_REGION_FB: + return &dev_priv->fb_heap; + default: + return 0; + } +} + +int radeon_mem_alloc( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_alloc_t alloc; + struct mem_block *block, **heap; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_mem_alloc_t *)data, + sizeof(alloc) ); + + heap = get_heap( dev_priv, alloc.region ); + if (!heap || !*heap) + return DRM_ERR(EFAULT); + + /* Make things easier on ourselves: all allocations at least + * 4k aligned. + */ + if (alloc.alignment < 12) + alloc.alignment = 12; + + block = alloc_block( *heap, alloc.size, alloc.alignment, + DRM_CURRENTPID ); + + if (!block) + return DRM_ERR(ENOMEM); + + if ( DRM_COPY_TO_USER( alloc.region_offset, &block->start, + sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} + + + +int radeon_mem_free( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_free_t memfree; + struct mem_block *block, **heap; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( memfree, (drm_radeon_mem_free_t *)data, + sizeof(memfree) ); + + heap = get_heap( dev_priv, memfree.region ); + if (!heap || !*heap) + return DRM_ERR(EFAULT); + + block = find_block( *heap, memfree.region_offset ); + if (!block) + return DRM_ERR(EFAULT); + + if (block->pid != DRM_CURRENTPID) + return DRM_ERR(EPERM); + + free_block( block ); + return 0; +} + +int radeon_mem_init_heap( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_mem_init_heap_t initheap; + struct mem_block **heap; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( initheap, (drm_radeon_mem_init_heap_t *)data, + sizeof(initheap) ); + + heap = get_heap( dev_priv, initheap.region ); + if (!heap) + return DRM_ERR(EFAULT); + + if (*heap) { + DRM_ERROR("heap already initialized?"); + return DRM_ERR(EFAULT); + } + + return init_heap( heap, initheap.start, initheap.size ); +} + + diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c index b0468a0..374cc5d 100644 --- a/sys/dev/drm/radeon_state.c +++ b/sys/dev/drm/radeon_state.c @@ -29,15 +29,12 @@ * $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/drm.h" +#include "dev/drm/drm_sarea.h" #include "dev/drm/radeon_drm.h" #include "dev/drm/radeon_drv.h" -#include "dev/drm/drm.h" /* ================================================================ @@ -53,360 +50,254 @@ static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv, 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", __func__ ); - - 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", __func__ ); - - 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", __func__ ); - - 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", __func__ ); - - 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", __func__ ); - - 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", __func__ ); - - 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", __func__ ); - - 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", __func__ ); - - 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", __func__ ); - - 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", __func__, 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", __func__, 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 ) +/* Emit 1.1 state + */ +static void radeon_emit_state( drm_radeon_private_t *dev_priv, + drm_radeon_context_regs_t *ctx, + drm_radeon_texture_regs_t *tex, + unsigned int dirty ) { - 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", __func__ ); - - 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", __func__, dirty ); + DRM_DEBUG( "dirty=0x%08x\n", dirty ); if ( dirty & RADEON_UPLOAD_CONTEXT ) { - radeon_emit_context( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_CONTEXT; + 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(); } if ( dirty & RADEON_UPLOAD_VERTFMT ) { - radeon_emit_vertfmt( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_VERTFMT; + BEGIN_RING( 2 ); + OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) ); + OUT_RING( ctx->se_coord_fmt ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_LINE ) { - radeon_emit_line( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_LINE; + 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(); } if ( dirty & RADEON_UPLOAD_BUMPMAP ) { - radeon_emit_bumpmap( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_BUMPMAP; + 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(); } if ( dirty & RADEON_UPLOAD_MASKS ) { - radeon_emit_masks( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_MASKS; + 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(); } if ( dirty & RADEON_UPLOAD_VIEWPORT ) { - radeon_emit_viewport( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_VIEWPORT; + 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(); } 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; + 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(); } if ( dirty & RADEON_UPLOAD_MISC ) { - radeon_emit_misc( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_MISC; + BEGIN_RING( 2 ); + OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) ); + OUT_RING( ctx->re_misc ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_TEX0 ) { - radeon_emit_tex0( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_TEX0; + BEGIN_RING( 9 ); + OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) ); + OUT_RING( tex[0].pp_txfilter ); + OUT_RING( tex[0].pp_txformat ); + OUT_RING( tex[0].pp_txoffset ); + OUT_RING( tex[0].pp_txcblend ); + OUT_RING( tex[0].pp_txablend ); + OUT_RING( tex[0].pp_tfactor ); + OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) ); + OUT_RING( tex[0].pp_border_color ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_TEX1 ) { - radeon_emit_tex1( dev_priv ); - sarea_priv->dirty &= ~RADEON_UPLOAD_TEX1; + BEGIN_RING( 9 ); + OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) ); + OUT_RING( tex[1].pp_txfilter ); + OUT_RING( tex[1].pp_txformat ); + OUT_RING( tex[1].pp_txoffset ); + OUT_RING( tex[1].pp_txcblend ); + OUT_RING( tex[1].pp_txablend ); + OUT_RING( tex[1].pp_tfactor ); + OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) ); + OUT_RING( tex[1].pp_border_color ); + ADVANCE_RING(); } if ( dirty & RADEON_UPLOAD_TEX2 ) { -#if 0 - radeon_emit_tex2( dev_priv ); -#endif - sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2; + BEGIN_RING( 9 ); + OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) ); + OUT_RING( tex[2].pp_txfilter ); + OUT_RING( tex[2].pp_txformat ); + OUT_RING( tex[2].pp_txoffset ); + OUT_RING( tex[2].pp_txcblend ); + OUT_RING( tex[2].pp_txablend ); + OUT_RING( tex[2].pp_tfactor ); + OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) ); + OUT_RING( tex[2].pp_border_color ); + ADVANCE_RING(); } +} - sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | - RADEON_UPLOAD_TEX1IMAGES | - RADEON_UPLOAD_TEX2IMAGES | - RADEON_REQUIRE_QUIESCENCE); +/* Emit 1.2 state + */ +static void radeon_emit_state2( drm_radeon_private_t *dev_priv, + drm_radeon_state_t *state ) +{ + RING_LOCALS; + + if (state->dirty & RADEON_UPLOAD_ZBIAS) { + BEGIN_RING( 3 ); + OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) ); + OUT_RING( state->context2.se_zbias_factor ); + OUT_RING( state->context2.se_zbias_constant ); + ADVANCE_RING(); + } + + radeon_emit_state( dev_priv, &state->context, + state->tex, state->dirty ); } +/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in + * 1.3 cmdbuffers allow all previous state to be updated as well as + * the tcl scalar and vector areas. + */ +static struct { + int start; + int len; + const char *name; +} packet[RADEON_MAX_STATE_PACKETS] = { + { RADEON_PP_MISC,7,"RADEON_PP_MISC" }, + { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" }, + { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" }, + { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" }, + { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" }, + { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" }, + { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" }, + { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" }, + { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" }, + { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" }, + { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" }, + { RADEON_RE_MISC,1,"RADEON_RE_MISC" }, + { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" }, + { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" }, + { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" }, + { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" }, + { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" }, + { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" }, + { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" }, + { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" }, + { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" }, + { R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0" }, + { R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" }, + { R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" }, + { R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" }, + { R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" }, + { R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" }, + { R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" }, + { R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" }, + { R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" }, + { R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" }, + { R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" }, + { R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" }, + { R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" }, + { R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" }, + { R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" }, + { R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" }, + { R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" }, + { R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" }, + { R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" }, + { R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" }, + { R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" }, + { R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" }, + { R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" }, + { R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" }, + { R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" }, + { R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" }, + { R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" }, + { R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" }, + { R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" }, + { R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" }, + { R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" }, + { R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" }, + { R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" }, + { R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" }, + { R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" }, + { R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" }, + { R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" }, + { R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" }, + { R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" }, + { R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" }, + { R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */ + { R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */ + { R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" }, + { R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" }, + { R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" }, + { R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" }, + { R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" }, + { R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" }, + { R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" }, + { R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" }, + { R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" }, + { R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" }, +}; + + -#if RADEON_PERFORMANCE_BOXES /* ================================================================ * Performance monitoring functions */ @@ -415,10 +306,12 @@ 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; + x += dev_priv->sarea_priv->boxes[0].x1; + y += dev_priv->sarea_priv->boxes[0].y1; + switch ( dev_priv->color_fmt ) { case RADEON_COLOR_FORMAT_RGB565: color = (((r & 0xf8) << 8) | @@ -431,8 +324,11 @@ static void radeon_clear_box( drm_radeon_private_t *dev_priv, break; } - offset = dev_priv->back_offset; - pitch = dev_priv->back_pitch >> 3; + BEGIN_RING( 4 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) ); + OUT_RING( 0xffffffff ); + ADVANCE_RING(); BEGIN_RING( 6 ); @@ -444,7 +340,12 @@ static void radeon_clear_box( drm_radeon_private_t *dev_priv, RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS ); - OUT_RING( (pitch << 22) | (offset >> 5) ); + if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { + OUT_RING( dev_priv->front_pitch_offset ); + } else { + OUT_RING( dev_priv->back_pitch_offset ); + } + OUT_RING( color ); OUT_RING( (x << 16) | y ); @@ -455,53 +356,77 @@ static void radeon_clear_box( drm_radeon_private_t *dev_priv, 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 ); + /* Collapse various things into a wait flag -- trying to + * guess if userspase slept -- better just to have them tell us. + */ + if (dev_priv->stats.last_frame_reads > 1 || + dev_priv->stats.last_clear_reads > dev_priv->stats.clears) { + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; } -} -#endif + if (dev_priv->stats.freelist_loops) { + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + } + + /* Purple box for page flipping + */ + if ( dev_priv->stats.boxes & RADEON_BOX_FLIP ) + radeon_clear_box( dev_priv, 4, 4, 8, 8, 255, 0, 255 ); + + /* Red box if we have to wait for idle at any point + */ + if ( dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE ) + radeon_clear_box( dev_priv, 16, 4, 8, 8, 255, 0, 0 ); + /* Blue box: lost context? + */ + + /* Yellow box for texture swaps + */ + if ( dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD ) + radeon_clear_box( dev_priv, 40, 4, 8, 8, 255, 255, 0 ); + /* Green box if hardware never idles (as far as we can tell) + */ + if ( !(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE) ) + radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 ); + + + /* Draw bars indicating number of buffers allocated + * (not a great measure, easily confused) + */ + if (dev_priv->stats.requested_bufs) { + if (dev_priv->stats.requested_bufs > 100) + dev_priv->stats.requested_bufs = 100; + + radeon_clear_box( dev_priv, 4, 16, + dev_priv->stats.requested_bufs, 4, + 196, 128, 128 ); + } + + memset( &dev_priv->stats, 0, sizeof(dev_priv->stats) ); + +} /* ================================================================ * 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; + drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; unsigned int flags = clear->flags; + u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0; int i; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "flags = 0x%x\n", flags ); + + dev_priv->stats.clears++; if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { unsigned int tmp = flags; @@ -511,127 +436,277 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev, 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; + if ( flags & (RADEON_FRONT | RADEON_BACK) ) { - DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n", - x, y, w, h, flags ); + BEGIN_RING( 4 ); - 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 ); - /* Ensure the 3D stream is idle before doing a - * 2D fill to clear the front or back buffer. - */ - RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); - OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) ); - OUT_RING( clear->color_mask ); + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->ctx_owner = 0; + + 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 ) { + 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(); + } + } + } - ADVANCE_RING(); + /* We have to clear the depth and/or stencil buffers by + * rendering a quad into just those buffers. Thus, we have to + * make sure the 3D engine is configured correctly. + */ + if ( dev_priv->is_r200 && + (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) { - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT | - RADEON_UPLOAD_MASKS); - } + int tempPP_CNTL; + int tempRE_CNTL; + int tempRB3D_CNTL; + int tempRB3D_ZSTENCILCNTL; + int tempRB3D_STENCILREFMASK; + int tempRB3D_PLANEMASK; + int tempSE_CNTL; + int tempSE_VTE_CNTL; + int tempSE_VTX_FMT_0; + int tempSE_VTX_FMT_1; + int tempSE_VAP_CNTL; + int tempRE_AUX_SCISSOR_CNTL; - if ( flags & RADEON_FRONT ) { - BEGIN_RING( 6 ); + tempPP_CNTL = 0; + tempRE_CNTL = 0; - 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 ); + tempRB3D_CNTL = depth_clear->rb3d_cntl; + tempRB3D_CNTL &= ~(1<<15); /* unset radeon magic flag */ - OUT_RING( dev_priv->front_pitch_offset ); - OUT_RING( clear->clear_color ); + tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; + tempRB3D_STENCILREFMASK = 0x0; - OUT_RING( (x << 16) | y ); - OUT_RING( (w << 16) | h ); + tempSE_CNTL = depth_clear->se_cntl; - ADVANCE_RING(); + + + /* Disable TCL */ + + tempSE_VAP_CNTL = (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */ + (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT)); + + tempRB3D_PLANEMASK = 0x0; + + tempRE_AUX_SCISSOR_CNTL = 0x0; + + tempSE_VTE_CNTL = + SE_VTE_CNTL__VTX_XY_FMT_MASK | + SE_VTE_CNTL__VTX_Z_FMT_MASK; + + /* Vertex format (X, Y, Z, W)*/ + tempSE_VTX_FMT_0 = + SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK | + SE_VTX_FMT_0__VTX_W0_PRESENT_MASK; + tempSE_VTX_FMT_1 = 0x0; + + + /* + * Depth buffer specific enables + */ + if (flags & RADEON_DEPTH) { + /* Enable depth buffer */ + tempRB3D_CNTL |= RADEON_Z_ENABLE; + } else { + /* Disable depth buffer */ + tempRB3D_CNTL &= ~RADEON_Z_ENABLE; } - if ( flags & RADEON_BACK ) { - BEGIN_RING( 6 ); + /* + * Stencil buffer specific enables + */ + if ( flags & RADEON_STENCIL ) { + tempRB3D_CNTL |= RADEON_STENCIL_ENABLE; + tempRB3D_STENCILREFMASK = clear->depth_mask; + } else { + tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE; + tempRB3D_STENCILREFMASK = 0x00000000; + } - 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 ); + BEGIN_RING( 26 ); + RADEON_WAIT_UNTIL_2D_IDLE(); + + OUT_RING_REG( RADEON_PP_CNTL, tempPP_CNTL ); + OUT_RING_REG( R200_RE_CNTL, tempRE_CNTL ); + OUT_RING_REG( RADEON_RB3D_CNTL, tempRB3D_CNTL ); + OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL, + tempRB3D_ZSTENCILCNTL ); + OUT_RING_REG( RADEON_RB3D_STENCILREFMASK, + tempRB3D_STENCILREFMASK ); + OUT_RING_REG( RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK ); + OUT_RING_REG( RADEON_SE_CNTL, tempSE_CNTL ); + OUT_RING_REG( R200_SE_VTE_CNTL, tempSE_VTE_CNTL ); + OUT_RING_REG( R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0 ); + OUT_RING_REG( R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1 ); + OUT_RING_REG( R200_SE_VAP_CNTL, tempSE_VAP_CNTL ); + OUT_RING_REG( R200_RE_AUX_SCISSOR_CNTL, + tempRE_AUX_SCISSOR_CNTL ); + ADVANCE_RING(); - OUT_RING( dev_priv->back_pitch_offset ); - OUT_RING( clear->clear_color ); + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->ctx_owner = 0; - OUT_RING( (x << 16) | y ); - OUT_RING( (w << 16) | h ); + for ( i = 0 ; i < nbox ; i++ ) { + + /* Funny that this should be required -- + * sets top-left? + */ + radeon_emit_clip_rect( dev_priv, + &sarea_priv->boxes[i] ); + BEGIN_RING( 14 ); + OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 12 ) ); + OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST | + RADEON_PRIM_WALK_RING | + (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( 0x3f800000 ); + 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( 0x3f800000 ); + OUT_RING( depth_boxes[i].ui[CLEAR_X2] ); + OUT_RING( depth_boxes[i].ui[CLEAR_Y2] ); + OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); + OUT_RING( 0x3f800000 ); ADVANCE_RING(); - } + } + else if ( (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) { + + rb3d_cntl = depth_clear->rb3d_cntl; if ( flags & RADEON_DEPTH ) { - drm_radeon_depth_clear_t *depth_clear = - &dev_priv->depth_clear; + rb3d_cntl |= RADEON_Z_ENABLE; + } else { + rb3d_cntl &= ~RADEON_Z_ENABLE; + } - if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeon_emit_state( dev_priv ); - } + if ( flags & RADEON_STENCIL ) { + rb3d_cntl |= RADEON_STENCIL_ENABLE; + rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */ + } else { + rb3d_cntl &= ~RADEON_STENCIL_ENABLE; + rb3d_stencilrefmask = 0x00000000; + } + + BEGIN_RING( 13 ); + RADEON_WAIT_UNTIL_2D_IDLE(); + + OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) ); + OUT_RING( 0x00000000 ); + OUT_RING( rb3d_cntl ); + + OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL, + depth_clear->rb3d_zstencilcntl ); + OUT_RING_REG( RADEON_RB3D_STENCILREFMASK, + rb3d_stencilrefmask ); + OUT_RING_REG( RADEON_RB3D_PLANEMASK, + 0x00000000 ); + OUT_RING_REG( RADEON_SE_CNTL, + depth_clear->se_cntl ); + ADVANCE_RING(); + + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->ctx_owner = 0; - /* FIXME: Render a rectangle to clear the depth - * buffer. So much for those "fast Z clears"... + for ( i = 0 ; i < nbox ; i++ ) { + + /* Funny that this should be required -- + * sets top-left? */ - 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 ); + radeon_emit_clip_rect( dev_priv, + &sarea_priv->boxes[i] ); + + BEGIN_RING( 15 ); + + OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) ); + OUT_RING( RADEON_VTX_Z_PRESENT | + RADEON_VTX_PKCOLOR_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( 0x0 ); 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( 0x0 ); OUT_RING( depth_boxes[i].ui[CLEAR_X2] ); OUT_RING( depth_boxes[i].ui[CLEAR_Y2] ); OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); + OUT_RING( 0x0 ); 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); } } @@ -657,13 +732,13 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) drm_clip_rect_t *pbox = sarea_priv->boxes; int i; RING_LOCALS; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); -#if RADEON_PERFORMANCE_BOXES /* Do some trivial performance monitoring... */ - radeon_cp_performance_boxes( dev_priv ); -#endif + if (dev_priv->do_boxes) + radeon_cp_performance_boxes( dev_priv ); + /* Wait for the 3D stream to idle before dispatching the bitblt. * This will prevent data corruption between the two streams. @@ -695,9 +770,17 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) 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 ); + + /* Make this work even if front & back are flipped: + */ + if (dev_priv->current_page == 0) { + OUT_RING( dev_priv->back_pitch_offset ); + OUT_RING( dev_priv->front_pitch_offset ); + } + else { + OUT_RING( dev_priv->front_pitch_offset ); + OUT_RING( dev_priv->back_pitch_offset ); + } OUT_RING( (x << 16) | y ); OUT_RING( (x << 16) | y ); @@ -723,29 +806,33 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) static void radeon_cp_dispatch_flip( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; + drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle; + int offset = (dev_priv->current_page == 1) + ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; - DRM_DEBUG( "%s: page=%d\n", __func__, dev_priv->current_page ); + DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", + __FUNCTION__, + dev_priv->current_page, + dev_priv->sarea_priv->pfCurrentPage); -#if RADEON_PERFORMANCE_BOXES /* Do some trivial performance monitoring... */ - radeon_cp_performance_boxes( dev_priv ); -#endif + if (dev_priv->do_boxes) { + dev_priv->stats.boxes |= RADEON_BOX_FLIP; + radeon_cp_performance_boxes( dev_priv ); + } + /* Update the frame offsets for both CRTCs + */ 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; - } + OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch + + sarea->frame.x + * ( dev_priv->color_fmt - 2 ) ) & ~7 ) + + offset ); + OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + + offset ); ADVANCE_RING(); @@ -754,6 +841,8 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = + 1 - dev_priv->current_page; BEGIN_RING( 2 ); @@ -762,82 +851,118 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) ADVANCE_RING(); } +static int bad_prim_vertex_nr( int primitive, int nr ) +{ + switch (primitive & RADEON_PRIM_TYPE_MASK) { + case RADEON_PRIM_TYPE_NONE: + case RADEON_PRIM_TYPE_POINT: + return nr < 1; + case RADEON_PRIM_TYPE_LINE: + return (nr & 1) || nr == 0; + case RADEON_PRIM_TYPE_LINE_STRIP: + return nr < 2; + case RADEON_PRIM_TYPE_TRI_LIST: + case RADEON_PRIM_TYPE_3VRT_POINT_LIST: + case RADEON_PRIM_TYPE_3VRT_LINE_LIST: + case RADEON_PRIM_TYPE_RECT_LIST: + return nr % 3 || nr == 0; + case RADEON_PRIM_TYPE_TRI_FAN: + case RADEON_PRIM_TYPE_TRI_STRIP: + return nr < 3; + default: + return 1; + } +} + + + +typedef struct { + unsigned int start; + unsigned int finish; + unsigned int prim; + unsigned int numverts; + unsigned int offset; + unsigned int vc_format; +} drm_radeon_tcl_prim_t; + static void radeon_cp_dispatch_vertex( drm_device_t *dev, - drm_buf_t *buf ) + drm_buf_t *buf, + drm_radeon_tcl_prim_t *prim, + drm_clip_rect_t *boxes, + int nbox ) + { 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; + drm_clip_rect_t box; + int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start; + int numverts = (int)prim->numverts; int i = 0; RING_LOCALS; - DRM_DEBUG( "%s: nbox=%d\n", __func__, sarea_priv->nbox ); - if ( 0 ) - radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty ); + DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n", + prim->prim, + prim->vc_format, + prim->start, + prim->finish, + prim->numverts); + + if (bad_prim_vertex_nr( prim->prim, prim->numverts )) { + DRM_ERROR( "bad prim %x numverts %d\n", + prim->prim, prim->numverts ); + return; + } - if ( buf->used ) { - buf_priv->dispatched = 1; + do { + /* Emit the next cliprect */ + if ( i < nbox ) { + if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) )) + return; - if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeon_emit_state( dev_priv ); + radeon_emit_clip_rect( dev_priv, &box ); } - 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 ); - /* 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( numverts ); + OUT_RING( prim->vc_format ); + OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST | + RADEON_COLOR_ORDER_RGBA | + RADEON_VTX_FMT_RADEON_MODE | + (numverts << RADEON_NUM_VERTICES_SHIFT) ); - 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(); - ADVANCE_RING(); + i++; + } while ( i < nbox ); +} - 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(); +static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_buf_priv_t *buf_priv = buf->dev_private; + RING_LOCALS; - buf->pending = 1; - buf->used = 0; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; - } + buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; - dev_priv->sarea_priv->last_dispatch++; + /* Emit the vertex buffer age */ + BEGIN_RING( 2 ); + RADEON_DISPATCH_AGE( buf_priv->age ); + ADVANCE_RING(); - sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS; - sarea_priv->nbox = 0; + buf->pending = 1; + buf->used = 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 ); @@ -858,8 +983,6 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, data[dwords++] = RADEON_CP_PACKET2; } - buf_priv->dispatched = 1; - /* Fire off the indirect buffer */ BEGIN_RING( 3 ); @@ -869,129 +992,114 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, 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_buf_t *elt_buf, + drm_radeon_tcl_prim_t *prim, + drm_clip_rect_t *boxes, + int nbox ) { 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; + drm_clip_rect_t box; + int offset = dev_priv->agp_buffers_offset + prim->offset; 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] ); - } + int start = prim->start + RADEON_INDEX_PRIM_OFFSET; + int count = (prim->finish - start) / sizeof(u16); + + DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", + prim->prim, + prim->vc_format, + prim->start, + prim->finish, + prim->offset, + prim->numverts); + + if (bad_prim_vertex_nr( prim->prim, count )) { + DRM_ERROR( "bad prim %x count %d\n", + prim->prim, count ); + return; + } - radeon_cp_dispatch_indirect( dev, buf, start, end ); - i++; - } while ( i < sarea_priv->nbox ); + if ( start >= prim->finish || + (prim->start & 0x7) ) { + DRM_ERROR( "buffer prim %d\n", prim->prim ); + return; } - 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(); + dwords = (prim->finish - prim->start + 3) / sizeof(u32); + + data = (u32 *)((char *)dev_priv->buffers->handle + + elt_buf->offset + prim->start); + + data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); + data[1] = offset; + data[2] = prim->numverts; + data[3] = prim->vc_format; + data[4] = (prim->prim | + RADEON_PRIM_WALK_IND | + RADEON_COLOR_ORDER_RGBA | + RADEON_VTX_FMT_RADEON_MODE | + (count << RADEON_NUM_VERTICES_SHIFT) ); + + do { + if ( i < nbox ) { + if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) )) + return; + + radeon_emit_clip_rect( dev_priv, &box ); + } - buf->pending = 1; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; - } + radeon_cp_dispatch_indirect( dev, elt_buf, + prim->start, + prim->finish ); - dev_priv->sarea_priv->last_dispatch++; + i++; + } while ( i < nbox ); - 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_tex_image_t *image ) { 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; + u32 height; + int i; RING_LOCALS; - /* FIXME: Be smarter about this... + dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; + + /* 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. */ - buf = radeon_freelist_get( dev ); - if ( !buf ) return DRM_OS_ERR(EAGAIN); + BEGIN_RING( 4 ); + RADEON_FLUSH_CACHE(); + RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); - 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 ); +#ifdef __BIG_ENDIAN + /* The Mesa texture functions provide the data in little endian as the + * chip wants it, but we need to compensate for the fact that the CP + * ring gets byte-swapped + */ + BEGIN_RING( 2 ); + OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT ); + ADVANCE_RING(); +#endif - 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 @@ -1008,6 +1116,8 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, case RADEON_TXFORMAT_ARGB1555: case RADEON_TXFORMAT_RGB565: case RADEON_TXFORMAT_ARGB4444: + case RADEON_TXFORMAT_VYUY422: + case RADEON_TXFORMAT_YVYU422: format = RADEON_COLOR_FORMAT_RGB565; tex_width = tex->width * 2; blit_width = image->width * 2; @@ -1020,128 +1130,123 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, break; default: DRM_ERROR( "invalid texture format %d\n", tex->format ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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; + DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width ); - if ( size > RADEON_MAX_TEXTURE_SIZE ) { - /* Texture image is too large, do a multipass upload */ - ret = EAGAIN; + do { + 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 ); - /* Adjust the blit size to fit the indirect buffer */ - height = RADEON_MAX_TEXTURE_SIZE / blit_width; + /* Make a copy of some parameters in case we have to + * update them for a multi-pass texture blit. + */ + height = image->height; + data = (const u8 *)image->data; + 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 ( size > RADEON_MAX_TEXTURE_SIZE ) { + height = RADEON_MAX_TEXTURE_SIZE / blit_width; + size = height * blit_width; + } else if ( size < 4 && size > 0 ) { + size = 4; + } else if ( size == 0 ) { + return 0; + } - if ( DRM_OS_COPYTOUSR( tex->image, image, sizeof(*image) ) ) { - DRM_ERROR( "EFAULT on tex->image\n" ); - return DRM_OS_ERR(EFAULT); + buf = radeon_freelist_get( dev ); + if ( 0 && !buf ) { + radeon_do_cp_idle( dev_priv ); + buf = radeon_freelist_get( dev ); + } + if ( !buf ) { + DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n"); + DRM_COPY_TO_USER( tex->image, image, sizeof(*image) ); + return DRM_ERR(EAGAIN); } - } 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 ); - return DRM_OS_ERR(EFAULT); - } - } else { - /* Texture image width is less than the minimum, so we - * need to pad out each image scanline to the minimum - * width. + /* Dispatch the indirect buffer. */ - 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 ); - return DRM_OS_ERR(EFAULT); + buffer = (u32*)((char*)dev_priv->buffers->handle + buf->offset); + dwords = size / 4; + 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] = (image->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_COPY_FROM_USER( buffer, data, + dwords * sizeof(u32) ) ) { + DRM_ERROR( "EFAULT on data, %d dwords\n", + dwords ); + return DRM_ERR(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_COPY_FROM_USER( buffer, data, + tex_width ) ) { + DRM_ERROR( "EFAULT on pad, %d bytes\n", + tex_width ); + return DRM_ERR(EFAULT); + } + buffer += 8; + data += tex_width; } - buffer += 8; - data += tex_width; } - } - buf->pid = pid; - buf->used = (dwords + 8) * sizeof(u32); - buf_priv->discard = 1; + buf->pid = DRM_CURRENTPID; + buf->used = (dwords + 8) * sizeof(u32); + radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); + radeon_cp_discard_buffer( dev, buf ); - radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); + /* Update the input parameters for next time */ + image->y += height; + image->height -= height; + (const u8 *)image->data += size; + } while (image->height > 0); /* 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(); - - return ret; + return 0; } + 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", __func__ ); + DRM_DEBUG( "\n" ); BEGIN_RING( 35 ); @@ -1161,18 +1266,18 @@ static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple ) * IOCTL functions */ -int radeon_cp_clear( DRM_OS_IOCTL ) +int radeon_cp_clear( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( clear, (drm_radeon_clear_t *) data, + DRM_COPY_FROM_USER_IOCTL( clear, (drm_radeon_clear_t *)data, sizeof(clear) ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1180,21 +1285,84 @@ int radeon_cp_clear( DRM_OS_IOCTL ) if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - if ( DRM_OS_COPYFROMUSR( &depth_boxes, clear.depth_boxes, + if ( DRM_COPY_FROM_USER( &depth_boxes, clear.depth_boxes, sarea_priv->nbox * sizeof(depth_boxes[0]) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(EFAULT); radeon_cp_dispatch_clear( dev, &clear, depth_boxes ); + COMMIT_RING(); + return 0; +} + + +/* Not sure why this isn't set all the time: + */ +static int radeon_do_init_pageflip( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG( "\n" ); + + BEGIN_RING( 6 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) ); + OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) ); + OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); + ADVANCE_RING(); + + dev_priv->page_flipping = 1; + dev_priv->current_page = 0; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; + + return 0; +} + +/* Called whenever a client dies, from DRM(release). + * NOTE: Lock isn't necessarily held when this is called! + */ +int radeon_do_cleanup_pageflip( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "\n" ); + + if (dev_priv->current_page != 0) + radeon_cp_dispatch_flip( dev ); + + dev_priv->page_flipping = 0; return 0; } -int radeon_cp_swap( DRM_OS_IOCTL ) +/* Swapping and flipping are different operations, need different ioctls. + * They can & should be intermixed to support multiple 3d windows. + */ +int radeon_cp_flip( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "\n" ); + + LOCK_TEST_WITH_RETURN( dev ); + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + + if (!dev_priv->page_flipping) + radeon_do_init_pageflip( dev ); + + radeon_cp_dispatch_flip( dev ); + + COMMIT_RING(); + return 0; +} + +int radeon_cp_swap( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - DRM_DEBUG( "%s\n", __func__ ); + DRM_DEBUG( "\n" ); LOCK_TEST_WITH_RETURN( dev ); @@ -1203,125 +1371,148 @@ int radeon_cp_swap( DRM_OS_IOCTL ) 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 ); - } + radeon_cp_dispatch_swap( dev ); + dev_priv->sarea_priv->ctx_owner = 0; + COMMIT_RING(); return 0; } -int radeon_cp_vertex( DRM_OS_IOCTL ) +int radeon_cp_vertex( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_vertex_t vertex; + drm_radeon_tcl_prim_t prim; LOCK_TEST_WITH_RETURN( dev ); if ( !dev_priv ) { - DRM_ERROR( "%s called with no initialization\n", __func__ ); - return DRM_OS_ERR(EINVAL); + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); } - DRM_OS_KRNFROMUSR( vertex, (drm_radeon_vertex_t *) data, + DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t *)data, sizeof(vertex) ); - DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n", - __func__, DRM_OS_CURRENTPID, + DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n", + DRM_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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) { DRM_ERROR( "buffer prim %d\n", vertex.prim ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ) { + if ( buf->pid != DRM_CURRENTPID ) { DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_OS_CURRENTPID, buf->pid ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", vertex.idx ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } - buf->used = vertex.count; - buf_priv->prim = vertex.prim; - buf_priv->discard = vertex.discard; + /* Build up a prim_t record: + */ + if (vertex.count) { + buf->used = vertex.count; /* not used? */ - radeon_cp_dispatch_vertex( dev, buf ); + if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { + radeon_emit_state( dev_priv, + &sarea_priv->context_state, + sarea_priv->tex_state, + sarea_priv->dirty ); + + sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | + RADEON_UPLOAD_TEX1IMAGES | + RADEON_UPLOAD_TEX2IMAGES | + RADEON_REQUIRE_QUIESCENCE); + } + + prim.start = 0; + prim.finish = vertex.count; /* unused */ + prim.prim = vertex.prim; + prim.numverts = vertex.count; + prim.vc_format = dev_priv->sarea_priv->vc_format; + + radeon_cp_dispatch_vertex( dev, buf, &prim, + dev_priv->sarea_priv->boxes, + dev_priv->sarea_priv->nbox ); + } + if (vertex.discard) { + radeon_cp_discard_buffer( dev, buf ); + } + + COMMIT_RING(); return 0; } -int radeon_cp_indices( DRM_OS_IOCTL ) +int radeon_cp_indices( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; - drm_radeon_buf_priv_t *buf_priv; drm_radeon_indices_t elts; + drm_radeon_tcl_prim_t prim; int count; LOCK_TEST_WITH_RETURN( dev ); if ( !dev_priv ) { - DRM_ERROR( "%s called with no initialization\n", __func__ ); - return DRM_OS_ERR(EINVAL); + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); } - DRM_OS_KRNFROMUSR( elts, (drm_radeon_indices_t *) data, + DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t *)data, sizeof(elts) ); - DRM_DEBUG( "%s: pid=%d index=%d start=%d end=%d discard=%d\n", - __func__, DRM_OS_CURRENTPID, + DRM_DEBUG( "pid=%d index=%d start=%d end=%d discard=%d\n", + DRM_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 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) { DRM_ERROR( "buffer prim %d\n", elts.prim ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ) { + if ( buf->pid != DRM_CURRENTPID ) { DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_OS_CURRENTPID, buf->pid ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", elts.idx ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } count = (elts.end - elts.start) / sizeof(u16); @@ -1329,89 +1520,119 @@ int radeon_cp_indices( DRM_OS_IOCTL ) if ( elts.start & 0x7 ) { DRM_ERROR( "misaligned buffer 0x%x\n", elts.start ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( elts.start < buf->used ) { DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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 ); + if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { + radeon_emit_state( dev_priv, + &sarea_priv->context_state, + sarea_priv->tex_state, + sarea_priv->dirty ); + + sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | + RADEON_UPLOAD_TEX1IMAGES | + RADEON_UPLOAD_TEX2IMAGES | + RADEON_REQUIRE_QUIESCENCE); + } + + + /* Build up a prim_t record: + */ + prim.start = elts.start; + prim.finish = elts.end; + prim.prim = elts.prim; + prim.offset = 0; /* offset from start of dma buffers */ + prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ + prim.vc_format = dev_priv->sarea_priv->vc_format; + + radeon_cp_dispatch_indices( dev, buf, &prim, + dev_priv->sarea_priv->boxes, + dev_priv->sarea_priv->nbox ); + if (elts.discard) { + radeon_cp_discard_buffer( dev, buf ); + } + COMMIT_RING(); return 0; } -int radeon_cp_texture( DRM_OS_IOCTL ) +int radeon_cp_texture( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_texture_t tex; drm_radeon_tex_image_t image; + int ret; LOCK_TEST_WITH_RETURN( dev ); - DRM_OS_KRNFROMUSR( tex, (drm_radeon_texture_t *) data, sizeof(tex) ); + DRM_COPY_FROM_USER_IOCTL( tex, (drm_radeon_texture_t *)data, sizeof(tex) ); if ( tex.image == NULL ) { DRM_ERROR( "null texture image!\n" ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } - if ( DRM_OS_COPYFROMUSR( &image, + if ( DRM_COPY_FROM_USER( &image, (drm_radeon_tex_image_t *)tex.image, sizeof(image) ) ) - return DRM_OS_ERR(EFAULT); + return DRM_ERR(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 ); + ret = radeon_cp_dispatch_texture( dev, &tex, &image ); + + COMMIT_RING(); + return ret; } -int radeon_cp_stipple( DRM_OS_IOCTL ) +int radeon_cp_stipple( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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, + DRM_COPY_FROM_USER_IOCTL( stipple, (drm_radeon_stipple_t *)data, sizeof(stipple) ); - if ( DRM_OS_COPYFROMUSR( &mask, stipple.mask, 32 * sizeof(u32) ) ) - return DRM_OS_ERR(EFAULT); + if ( DRM_COPY_FROM_USER( &mask, stipple.mask, 32 * sizeof(u32) ) ) + return DRM_ERR(EFAULT); RING_SPACE_TEST_WITH_RETURN( dev_priv ); radeon_cp_dispatch_stipple( dev, mask ); + COMMIT_RING(); return 0; } -int radeon_cp_indirect( DRM_OS_IOCTL ) +int radeon_cp_indirect( DRM_IOCTL_ARGS ) { - DRM_OS_DEVICE; + DRM_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", __func__ ); - return DRM_OS_ERR(EINVAL); + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); } - DRM_OS_KRNFROMUSR( indirect, (drm_radeon_indirect_t *) data, + DRM_COPY_FROM_USER_IOCTL( indirect, (drm_radeon_indirect_t *)data, sizeof(indirect) ); DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n", @@ -1421,33 +1642,31 @@ int radeon_cp_indirect( DRM_OS_IOCTL ) if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) { DRM_ERROR( "buffer index %d (of %d max)\n", indirect.idx, dma->buf_count - 1 ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } buf = dma->buflist[indirect.idx]; - buf_priv = buf->dev_private; - if ( buf->pid != DRM_OS_CURRENTPID ) { + if ( buf->pid != DRM_CURRENTPID ) { DRM_ERROR( "process %d using buffer owned by %d\n", - DRM_OS_CURRENTPID, buf->pid ); - return DRM_OS_ERR(EINVAL); + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", indirect.idx ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(EINVAL); } if ( indirect.start < buf->used ) { DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n", indirect.start, buf->used ); - return DRM_OS_ERR(EINVAL); + return DRM_ERR(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. @@ -1463,6 +1682,523 @@ int radeon_cp_indirect( DRM_OS_IOCTL ) * privileged clients. */ radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end ); + if (indirect.discard) { + radeon_cp_discard_buffer( dev, buf ); + } + + + COMMIT_RING(); + return 0; +} + +int radeon_cp_vertex2( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; + drm_radeon_vertex2_t vertex; + int i; + unsigned char laststate; + + LOCK_TEST_WITH_RETURN( dev ); + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data, + sizeof(vertex) ); + + DRM_DEBUG( "pid=%d index=%d discard=%d\n", + DRM_CURRENTPID, + vertex.idx, 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 ); + return DRM_ERR(EINVAL); + } + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_TEST_WITH_RETURN( dev_priv ); + + buf = dma->buflist[vertex.idx]; + + if ( buf->pid != DRM_CURRENTPID ) { + DRM_ERROR( "process %d using buffer owned by %d\n", + DRM_CURRENTPID, buf->pid ); + return DRM_ERR(EINVAL); + } + + if ( buf->pending ) { + DRM_ERROR( "sending pending buffer %d\n", vertex.idx ); + return DRM_ERR(EINVAL); + } + + if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) + return DRM_ERR(EINVAL); + + for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) { + drm_radeon_prim_t prim; + drm_radeon_tcl_prim_t tclprim; + + if ( DRM_COPY_FROM_USER( &prim, &vertex.prim[i], sizeof(prim) ) ) + return DRM_ERR(EFAULT); + + if ( prim.stateidx != laststate ) { + drm_radeon_state_t state; + + if ( DRM_COPY_FROM_USER( &state, + &vertex.state[prim.stateidx], + sizeof(state) ) ) + return DRM_ERR(EFAULT); + + radeon_emit_state2( dev_priv, &state ); + + laststate = prim.stateidx; + } + + tclprim.start = prim.start; + tclprim.finish = prim.finish; + tclprim.prim = prim.prim; + tclprim.vc_format = prim.vc_format; + + if ( prim.prim & RADEON_PRIM_WALK_IND ) { + tclprim.offset = prim.numverts * 64; + tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ + + radeon_cp_dispatch_indices( dev, buf, &tclprim, + sarea_priv->boxes, + sarea_priv->nbox); + } else { + tclprim.numverts = prim.numverts; + tclprim.offset = 0; /* not used */ + + radeon_cp_dispatch_vertex( dev, buf, &tclprim, + sarea_priv->boxes, + sarea_priv->nbox); + } + + if (sarea_priv->nbox == 1) + sarea_priv->nbox = 0; + } + + if ( vertex.discard ) { + radeon_cp_discard_buffer( dev, buf ); + } + + COMMIT_RING(); + return 0; +} + + +static int radeon_emit_packets( + drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + int id = (int)header.packet.packet_id; + int sz, reg; + int *data = (int *)cmdbuf->buf; + RING_LOCALS; + + if (id >= RADEON_MAX_STATE_PACKETS) + return DRM_ERR(EINVAL); + + sz = packet[id].len; + reg = packet[id].start; + + if (sz * sizeof(int) > cmdbuf->bufsz) + return DRM_ERR(EINVAL); + + BEGIN_RING(sz+1); + OUT_RING( CP_PACKET0( reg, (sz-1) ) ); + OUT_RING_USER_TABLE( data, sz ); + ADVANCE_RING(); + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + +static __inline__ int radeon_emit_scalars( + drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + int sz = header.scalars.count; + int *data = (int *)cmdbuf->buf; + int start = header.scalars.offset; + int stride = header.scalars.stride; + RING_LOCALS; + + BEGIN_RING( 3+sz ); + OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) ); + OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); + OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) ); + OUT_RING_USER_TABLE( data, sz ); + ADVANCE_RING(); + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + +/* God this is ugly + */ +static __inline__ int radeon_emit_scalars2( + drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + int sz = header.scalars.count; + int *data = (int *)cmdbuf->buf; + int start = ((unsigned int)header.scalars.offset) + 0x100; + int stride = header.scalars.stride; + RING_LOCALS; + + BEGIN_RING( 3+sz ); + OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) ); + OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); + OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) ); + OUT_RING_USER_TABLE( data, sz ); + ADVANCE_RING(); + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + +static __inline__ int radeon_emit_vectors( + drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + int sz = header.vectors.count; + int *data = (int *)cmdbuf->buf; + int start = header.vectors.offset; + int stride = header.vectors.stride; + RING_LOCALS; + + BEGIN_RING( 3+sz ); + OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) ); + OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); + OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) ); + OUT_RING_USER_TABLE( data, sz ); + ADVANCE_RING(); + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + + +static int radeon_emit_packet3( drm_device_t *dev, + drm_radeon_cmd_buffer_t *cmdbuf ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int cmdsz, tmp; + int *cmd = (int *)cmdbuf->buf; + RING_LOCALS; + + + DRM_DEBUG("\n"); + + if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0])) + return DRM_ERR(EFAULT); + + cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16); + + if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 || + cmdsz * 4 > cmdbuf->bufsz) + return DRM_ERR(EINVAL); + + BEGIN_RING( cmdsz ); + OUT_RING_USER_TABLE( cmd, cmdsz ); + ADVANCE_RING(); + + cmdbuf->buf += cmdsz * 4; + cmdbuf->bufsz -= cmdsz * 4; + return 0; +} + + +static int radeon_emit_packet3_cliprect( drm_device_t *dev, + drm_radeon_cmd_buffer_t *cmdbuf, + int orig_nbox ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_clip_rect_t box; + int cmdsz, tmp; + int *cmd = (int *)cmdbuf->buf; + drm_clip_rect_t *boxes = cmdbuf->boxes; + int i = 0; + RING_LOCALS; + + DRM_DEBUG("\n"); + + if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0])) + return DRM_ERR(EFAULT); + + cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16); + + if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 || + cmdsz * 4 > cmdbuf->bufsz) + return DRM_ERR(EINVAL); + + if (!orig_nbox) + goto out; + + do { + if ( i < cmdbuf->nbox ) { + if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) )) + return DRM_ERR(EFAULT); + /* FIXME The second and subsequent times round + * this loop, send a WAIT_UNTIL_3D_IDLE before + * calling emit_clip_rect(). This fixes a + * lockup on fast machines when sending + * several cliprects with a cmdbuf, as when + * waving a 2D window over a 3D + * window. Something in the commands from user + * space seems to hang the card when they're + * sent several times in a row. That would be + * the correct place to fix it but this works + * around it until I can figure that out - Tim + * Smith */ + if ( i ) { + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + } + radeon_emit_clip_rect( dev_priv, &box ); + } + + BEGIN_RING( cmdsz ); + OUT_RING_USER_TABLE( cmd, cmdsz ); + ADVANCE_RING(); + + } while ( ++i < cmdbuf->nbox ); + if (cmdbuf->nbox == 1) + cmdbuf->nbox = 0; + + out: + cmdbuf->buf += cmdsz * 4; + cmdbuf->bufsz -= cmdsz * 4; + return 0; +} + + +static int radeon_emit_wait( drm_device_t *dev, int flags ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + + DRM_DEBUG("%s: %x\n", __FUNCTION__, flags); + switch (flags) { + case RADEON_WAIT_2D: + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_2D_IDLE(); + ADVANCE_RING(); + break; + case RADEON_WAIT_3D: + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_3D_IDLE(); + ADVANCE_RING(); + break; + case RADEON_WAIT_2D|RADEON_WAIT_3D: + BEGIN_RING( 2 ); + RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); + break; + default: + return DRM_ERR(EINVAL); + } + + return 0; +} + +int radeon_cp_cmdbuf( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf = 0; + int idx; + drm_radeon_cmd_buffer_t cmdbuf; + drm_radeon_cmd_header_t header; + int orig_nbox; + + LOCK_TEST_WITH_RETURN( dev ); + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data, + sizeof(cmdbuf) ); + + RING_SPACE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_TEST_WITH_RETURN( dev_priv ); + + + if (DRM_VERIFYAREA_READ( cmdbuf.buf, cmdbuf.bufsz )) + return DRM_ERR(EFAULT); + + if (cmdbuf.nbox && + DRM_VERIFYAREA_READ(cmdbuf.boxes, + cmdbuf.nbox * sizeof(drm_clip_rect_t))) + return DRM_ERR(EFAULT); + + orig_nbox = cmdbuf.nbox; + + while ( cmdbuf.bufsz >= sizeof(header) ) { + + if (DRM_GET_USER_UNCHECKED( header.i, (int *)cmdbuf.buf )) { + DRM_ERROR("__get_user %p\n", cmdbuf.buf); + return DRM_ERR(EFAULT); + } + + cmdbuf.buf += sizeof(header); + cmdbuf.bufsz -= sizeof(header); + + switch (header.header.cmd_type) { + case RADEON_CMD_PACKET: + DRM_DEBUG("RADEON_CMD_PACKET\n"); + if (radeon_emit_packets( dev_priv, header, &cmdbuf )) { + DRM_ERROR("radeon_emit_packets failed\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CMD_SCALARS: + DRM_DEBUG("RADEON_CMD_SCALARS\n"); + if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) { + DRM_ERROR("radeon_emit_scalars failed\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CMD_VECTORS: + DRM_DEBUG("RADEON_CMD_VECTORS\n"); + if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) { + DRM_ERROR("radeon_emit_vectors failed\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CMD_DMA_DISCARD: + DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); + idx = header.dma.buf_idx; + if ( idx < 0 || idx >= dma->buf_count ) { + DRM_ERROR( "buffer index %d (of %d max)\n", + idx, dma->buf_count - 1 ); + return DRM_ERR(EINVAL); + } + + buf = dma->buflist[idx]; + if ( buf->pid != DRM_CURRENTPID || buf->pending ) { + DRM_ERROR( "bad buffer\n" ); + return DRM_ERR(EINVAL); + } + + radeon_cp_discard_buffer( dev, buf ); + break; + + case RADEON_CMD_PACKET3: + DRM_DEBUG("RADEON_CMD_PACKET3\n"); + if (radeon_emit_packet3( dev, &cmdbuf )) { + DRM_ERROR("radeon_emit_packet3 failed\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CMD_PACKET3_CLIP: + DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); + if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) { + DRM_ERROR("radeon_emit_packet3_clip failed\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CMD_SCALARS2: + DRM_DEBUG("RADEON_CMD_SCALARS2\n"); + if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) { + DRM_ERROR("radeon_emit_scalars2 failed\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CMD_WAIT: + DRM_DEBUG("RADEON_CMD_WAIT\n"); + if (radeon_emit_wait( dev, header.wait.flags )) { + DRM_ERROR("radeon_emit_wait failed\n"); + return DRM_ERR(EINVAL); + } + break; + default: + DRM_ERROR("bad cmd_type %d at %p\n", + header.header.cmd_type, + cmdbuf.buf - sizeof(header)); + return DRM_ERR(EINVAL); + } + } + + + DRM_DEBUG("DONE\n"); + COMMIT_RING(); + return 0; +} + + +int radeon_cp_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_radeon_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case RADEON_PARAM_AGP_BUFFER_OFFSET: + value = dev_priv->agp_buffers_offset; + break; + case RADEON_PARAM_LAST_FRAME: + dev_priv->stats.last_frame_reads++; + value = GET_SCRATCH( 0 ); + break; + case RADEON_PARAM_LAST_DISPATCH: + value = GET_SCRATCH( 1 ); + break; + case RADEON_PARAM_LAST_CLEAR: + dev_priv->stats.last_clear_reads++; + value = GET_SCRATCH( 2 ); + break; + case RADEON_PARAM_IRQ_NR: + value = dev->irq; + break; + case RADEON_PARAM_AGP_BASE: + value = dev_priv->agp_vm_start; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + return 0; } diff --git a/sys/dev/drm/sis_drm.h b/sys/dev/drm/sis_drm.h deleted file mode 100644 index 76a3ba3..0000000 --- a/sys/dev/drm/sis_drm.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * $FreeBSD$ - */ - -#ifndef _sis_drm_public_h_ -#define _sis_drm_public_h_ - -/* 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) - -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_drv.c b/sys/dev/drm/tdfx_drv.c index 359cfc2..296777e 100644 --- a/sys/dev/drm/tdfx_drv.c +++ b/sys/dev/drm/tdfx_drv.c @@ -32,16 +32,6 @@ * $FreeBSD$ */ -#ifdef __linux__ -#include <linux/config.h> -#endif /* __linux__ */ - -#ifdef __FreeBSD__ -#include <sys/types.h> -#include <sys/bus.h> -#include <pci/pcivar.h> -#endif /* __FreeBSD__ */ - #include "dev/drm/tdfx.h" #include "dev/drm/drmP.h" @@ -74,10 +64,8 @@ #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. +/* List acquired from http://www.yourvote.com/pci/pcihdr.h and xc/xc/programs/Xserver/hw/xfree86/common/xf86PciInfo.h + * Please report to anholt@teleport.com inaccuracies or if a chip you have works that is marked unsupported here. */ drm_chipinfo_t DRM(devicelist)[] = { {0x121a, 0x0003, 1, "3dfx Voodoo Banshee"}, @@ -87,22 +75,7 @@ drm_chipinfo_t DRM(devicelist)[] = { {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" @@ -111,41 +84,17 @@ static drm_pci_list_t DRM(idlist)[] = { #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" +#ifdef __FreeBSD__ DRIVER_MODULE(tdfx, pci, tdfx_driver, tdfx_devclass, 0, 0); +#elif defined(__NetBSD__) +CFDRIVER_DECL(tdfx, DV_TTY, NULL); #endif /* __FreeBSD__ */ diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 1fa110e..6b1c109 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -428,17 +428,16 @@ device acpi options ACPI_DEBUG # DRM options: -# gammadrm: 3Dlabs Oxygen GMX 2000 # mgadrm: AGP Matrox G200, G400, G450, G550 # tdfxdrm: 3dfx Voodoo 3/4/5 and Banshee -# r128drm: AGP ATI Rage 128 -# radeondrm: AGP ATI Radeon, including 7200 and 7500 +# r128drm: ATI Rage 128 +# radeondrm: ATI Radeon up to 9000/9100 # DRM_LINUX: include linux compatibility, requires COMPAT_LINUX -# DRM_DEBUG: include debugging code, very slow +# DRM_DEBUG: include debug printfs, very slow # -# mga, r128, and radeon require AGP in the kernel +# mga requires AGP in the kernel, and it is recommended +# for AGP r128 and radeon cards. -device gammadrm device mgadrm device "r128drm" device radeondrm diff --git a/sys/modules/drm/Makefile b/sys/modules/drm/Makefile index 0a37484..6657994 100644 --- a/sys/modules/drm/Makefile +++ b/sys/modules/drm/Makefile @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR = gamma mga r128 radeon tdfx +SUBDIR = mga r128 radeon tdfx .include <bsd.subdir.mk> diff --git a/sys/modules/drm/gamma/Makefile b/sys/modules/drm/gamma/Makefile deleted file mode 100644 index 3931c9d..0000000 --- a/sys/modules/drm/gamma/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../../dev/drm -KMOD = gamma -NOMAN = YES -SRCS = gamma_drv.c gamma_dma.c -SRCS += device_if.h bus_if.h pci_if.h opt_drm.h - -.include <bsd.kmod.mk> diff --git a/sys/modules/drm/mga/Makefile b/sys/modules/drm/mga/Makefile index 78fb75f..2199a0b 100644 --- a/sys/modules/drm/mga/Makefile +++ b/sys/modules/drm/mga/Makefile @@ -3,7 +3,8 @@ .PATH: ${.CURDIR}/../../../dev/drm KMOD = mga NOMAN = YES -SRCS = mga_drv.c mga_state.c mga_warp.c mga_dma.c +SRCS = mga_drv.c mga_state.c mga_warp.c mga_dma.c \ + mga_irq.c SRCS +=device_if.h bus_if.h pci_if.h opt_drm.h .include <bsd.kmod.mk> diff --git a/sys/modules/drm/r128/Makefile b/sys/modules/drm/r128/Makefile index 7d699e8..822a1fe 100644 --- a/sys/modules/drm/r128/Makefile +++ b/sys/modules/drm/r128/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../../dev/drm KMOD = r128 NOMAN = YES -SRCS = r128_cce.c r128_drv.c r128_state.c +SRCS = r128_cce.c r128_drv.c r128_irq.c r128_state.c SRCS +=device_if.h bus_if.h pci_if.h opt_drm.h .include <bsd.kmod.mk> diff --git a/sys/modules/drm/radeon/Makefile b/sys/modules/drm/radeon/Makefile index 7d7d91e..7a3fad7 100644 --- a/sys/modules/drm/radeon/Makefile +++ b/sys/modules/drm/radeon/Makefile @@ -3,7 +3,8 @@ .PATH: ${.CURDIR}/../../../dev/drm KMOD = radeon NOMAN = YES -SRCS = radeon_cp.c radeon_drv.c radeon_state.c +SRCS = radeon_cp.c radeon_drv.c radeon_irq.c \ + radeon_mem.c radeon_state.c SRCS +=device_if.h bus_if.h pci_if.h opt_drm.h .include <bsd.kmod.mk> |