Drop shared-core, bsd-core, linux-core and scripts subdirs
parent
a66cf9ce68
commit
9dd3613073
|
@ -1,11 +0,0 @@
|
|||
SHARED= ../shared-core
|
||||
|
||||
SUBDIR = drm mach64 mga r128 radeon savage sis tdfx i915 #nouveau
|
||||
|
||||
.include <bsd.obj.mk>
|
||||
|
||||
depend: drm_pciids.h
|
||||
all: drm_pciids.h
|
||||
|
||||
drm_pciids.h: ${SHARED}/drm_pciids.txt
|
||||
sh ../scripts/create_bsd_pci_lists.sh < ${SHARED}/drm_pciids.txt
|
|
@ -1,219 +0,0 @@
|
|||
/*-
|
||||
* 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>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file ati_pcigart.c
|
||||
* Implementation of ATI's PCIGART, which provides an aperture in card virtual
|
||||
* address space with addresses remapped to system memory.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
|
||||
#define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1))
|
||||
|
||||
#define ATI_PCIE_WRITE 0x4
|
||||
#define ATI_PCIE_READ 0x8
|
||||
|
||||
static void
|
||||
drm_ati_alloc_pcigart_table_cb(void *arg, bus_dma_segment_t *segs,
|
||||
int nsegs, int error)
|
||||
{
|
||||
struct drm_dma_handle *dmah = arg;
|
||||
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
KASSERT(nsegs == 1,
|
||||
("drm_ati_alloc_pcigart_table_cb: bad dma segment count"));
|
||||
|
||||
dmah->busaddr = segs[0].ds_addr;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_ati_alloc_pcigart_table(struct drm_device *dev,
|
||||
struct drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
struct drm_dma_handle *dmah;
|
||||
int flags, ret;
|
||||
|
||||
dmah = malloc(sizeof(struct drm_dma_handle), DRM_MEM_DMA,
|
||||
M_ZERO | M_NOWAIT);
|
||||
if (dmah == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
DRM_UNLOCK();
|
||||
ret = bus_dma_tag_create(NULL, PAGE_SIZE, 0, /* tag, align, boundary */
|
||||
gart_info->table_mask, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
|
||||
NULL, NULL, /* filtfunc, filtfuncargs */
|
||||
gart_info->table_size, 1, /* maxsize, nsegs */
|
||||
gart_info->table_size, /* maxsegsize */
|
||||
BUS_DMA_ALLOCNOW, NULL, NULL, /* flags, lockfunc, lockfuncargs */
|
||||
&dmah->tag);
|
||||
if (ret != 0) {
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
flags = BUS_DMA_NOWAIT | BUS_DMA_ZERO;
|
||||
if (gart_info->gart_reg_if == DRM_ATI_GART_IGP)
|
||||
flags |= BUS_DMA_NOCACHE;
|
||||
|
||||
ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr, flags, &dmah->map);
|
||||
if (ret != 0) {
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
return ENOMEM;
|
||||
}
|
||||
DRM_LOCK();
|
||||
|
||||
ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
|
||||
gart_info->table_size, drm_ati_alloc_pcigart_table_cb, dmah, 0);
|
||||
if (ret != 0) {
|
||||
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
dev->sg->dmah = dmah;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
drm_ati_free_pcigart_table(struct drm_device *dev,
|
||||
struct drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
struct drm_dma_handle *dmah = dev->sg->dmah;
|
||||
|
||||
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
dev->sg->dmah = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
drm_ati_pcigart_cleanup(struct drm_device *dev,
|
||||
struct drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
/* we need to support large memory configurations */
|
||||
if (dev->sg == NULL) {
|
||||
DRM_ERROR("no scatter/gather memory!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gart_info->bus_addr) {
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
gart_info->bus_addr = 0;
|
||||
if (dev->sg->dmah)
|
||||
drm_ati_free_pcigart_table(dev, gart_info);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
drm_ati_pcigart_init(struct drm_device *dev,
|
||||
struct drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
void *address = NULL;
|
||||
unsigned long pages;
|
||||
u32 *pci_gart, page_base;
|
||||
dma_addr_t bus_address = 0;
|
||||
dma_addr_t entry_addr;
|
||||
int i, j, ret = 0;
|
||||
int max_pages;
|
||||
|
||||
/* we need to support large memory configurations */
|
||||
if (dev->sg == NULL) {
|
||||
DRM_ERROR("no scatter/gather memory!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
|
||||
|
||||
ret = drm_ati_alloc_pcigart_table(dev, gart_info);
|
||||
if (ret) {
|
||||
DRM_ERROR("cannot allocate PCI GART page!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
address = (void *)dev->sg->dmah->vaddr;
|
||||
bus_address = dev->sg->dmah->busaddr;
|
||||
} else {
|
||||
address = gart_info->addr;
|
||||
bus_address = gart_info->bus_addr;
|
||||
DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
|
||||
(unsigned int)bus_address, (unsigned long)address);
|
||||
}
|
||||
|
||||
pci_gart = (u32 *) address;
|
||||
|
||||
max_pages = (gart_info->table_size / sizeof(u32));
|
||||
pages = (dev->sg->pages <= max_pages)
|
||||
? dev->sg->pages : max_pages;
|
||||
|
||||
memset(pci_gart, 0, max_pages * sizeof(u32));
|
||||
|
||||
KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE, ("page size too small"));
|
||||
|
||||
for (i = 0; i < pages; i++) {
|
||||
entry_addr = dev->sg->busaddr[i];
|
||||
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
|
||||
page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK;
|
||||
switch(gart_info->gart_reg_if) {
|
||||
case DRM_ATI_GART_IGP:
|
||||
page_base |=
|
||||
(upper_32_bits(entry_addr) & 0xff) << 4;
|
||||
page_base |= 0xc;
|
||||
break;
|
||||
case DRM_ATI_GART_PCIE:
|
||||
page_base >>= 8;
|
||||
page_base |=
|
||||
(upper_32_bits(entry_addr) & 0xff) << 24;
|
||||
page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;
|
||||
break;
|
||||
default:
|
||||
case DRM_ATI_GART_PCI:
|
||||
break;
|
||||
}
|
||||
*pci_gart = cpu_to_le32(page_base);
|
||||
pci_gart++;
|
||||
entry_addr += ATI_PCIGART_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
done:
|
||||
gart_info->addr = address;
|
||||
gart_info->bus_addr = bus_address;
|
||||
return ret;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../shared-core/drm.h
|
|
@ -1,41 +0,0 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
KMOD = drm
|
||||
NO_MAN = YES
|
||||
SRCS = \
|
||||
ati_pcigart.c \
|
||||
drm_agpsupport.c \
|
||||
drm_auth.c \
|
||||
drm_bufs.c \
|
||||
drm_context.c \
|
||||
drm_dma.c \
|
||||
drm_drawable.c \
|
||||
drm_drv.c \
|
||||
drm_fops.c \
|
||||
drm_ioctl.c \
|
||||
drm_irq.c \
|
||||
drm_lock.c \
|
||||
drm_memory.c \
|
||||
drm_pci.c \
|
||||
drm_scatter.c \
|
||||
drm_sysctl.c \
|
||||
drm_vm.c
|
||||
|
||||
SRCS += device_if.h bus_if.h pci_if.h opt_drm.h
|
||||
CFLAGS += ${DEBUG_FLAGS} -I. -I..
|
||||
|
||||
.if defined(DRM_DEBUG)
|
||||
DRM_DEBUG_OPT= "\#define DRM_DEBUG 1"
|
||||
.endif
|
||||
|
||||
.if !defined(DRM_NOLINUX)
|
||||
DRM_LINUX_OPT= "\#define DRM_LINUX 1"
|
||||
.endif
|
||||
|
||||
opt_drm.h:
|
||||
touch opt_drm.h
|
||||
echo $(DRM_DEBUG_OPT) >> opt_drm.h
|
||||
echo $(DRM_LINUX_OPT) >> opt_drm.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
1019
bsd-core/drmP.h
1019
bsd-core/drmP.h
File diff suppressed because it is too large
Load Diff
|
@ -1,466 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_agpsupport.c
|
||||
* Support code for tying the kernel AGP support to DRM drivers and
|
||||
* the DRM's AGP ioctls.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#if __FreeBSD_version >= 800004
|
||||
#include <dev/agp/agpreg.h>
|
||||
#else /* __FreeBSD_version >= 800004 */
|
||||
#include <pci/agpreg.h>
|
||||
#endif /* __FreeBSD_version >= 800004 */
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
||||
/* Returns 1 if AGP or 0 if not. */
|
||||
static int
|
||||
drm_device_find_capability(struct drm_device *dev, int cap)
|
||||
{
|
||||
#if __FreeBSD_version >= 602102
|
||||
|
||||
return (pci_find_extcap(dev->device, cap, NULL) == 0);
|
||||
#else
|
||||
/* Code taken from agp.c. IWBNI that was a public interface. */
|
||||
u_int32_t status;
|
||||
u_int8_t ptr, next;
|
||||
|
||||
/*
|
||||
* Check the CAP_LIST bit of the PCI status register first.
|
||||
*/
|
||||
status = pci_read_config(dev->device, PCIR_STATUS, 2);
|
||||
if (!(status & 0x10))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Traverse the capabilities list.
|
||||
*/
|
||||
for (ptr = pci_read_config(dev->device, AGP_CAPPTR, 1);
|
||||
ptr != 0;
|
||||
ptr = next) {
|
||||
u_int32_t capid = pci_read_config(dev->device, ptr, 4);
|
||||
next = AGP_CAPID_GET_NEXT_PTR(capid);
|
||||
|
||||
/*
|
||||
* If this capability entry ID is cap, then we are done.
|
||||
*/
|
||||
if (AGP_CAPID_GET_CAP_ID(capid) == cap)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int drm_device_is_agp(struct drm_device *dev)
|
||||
{
|
||||
if (dev->driver->device_is_agp != NULL) {
|
||||
int ret;
|
||||
|
||||
/* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely
|
||||
* AGP, 2 = fall back to PCI capability
|
||||
*/
|
||||
ret = (*dev->driver->device_is_agp)(dev);
|
||||
if (ret != DRM_MIGHT_BE_AGP)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (drm_device_find_capability(dev, PCIY_AGP));
|
||||
}
|
||||
|
||||
int drm_device_is_pcie(struct drm_device *dev)
|
||||
{
|
||||
return (drm_device_find_capability(dev, PCIY_EXPRESS));
|
||||
}
|
||||
|
||||
int drm_agp_info(struct drm_device * dev, struct drm_agp_info *info)
|
||||
{
|
||||
struct agp_info *kern;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
kern = &dev->agp->info;
|
||||
agp_get_info(dev->agp->agpdev, kern);
|
||||
info->agp_version_major = 1;
|
||||
info->agp_version_minor = 0;
|
||||
info->mode = kern->ai_mode;
|
||||
info->aperture_base = kern->ai_aperture_base;
|
||||
info->aperture_size = kern->ai_aperture_size;
|
||||
info->memory_allowed = kern->ai_memory_allowed;
|
||||
info->memory_used = kern->ai_memory_used;
|
||||
info->id_vendor = kern->ai_devid & 0xffff;
|
||||
info->id_device = kern->ai_devid >> 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_info_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
int err;
|
||||
struct drm_agp_info info;
|
||||
|
||||
err = drm_agp_info(dev, &info);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
*(struct drm_agp_info *) data = info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
|
||||
return drm_agp_acquire(dev);
|
||||
}
|
||||
|
||||
int drm_agp_acquire(struct drm_device *dev)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
if (!dev->agp || dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
retcode = agp_acquire(dev->agp->agpdev);
|
||||
if (retcode)
|
||||
return retcode;
|
||||
|
||||
dev->agp->acquired = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_release_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
|
||||
return drm_agp_release(dev);
|
||||
}
|
||||
|
||||
int drm_agp_release(struct drm_device * dev)
|
||||
{
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
agp_release(dev->agp->agpdev);
|
||||
dev->agp->acquired = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
|
||||
{
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
dev->agp->mode = mode.mode;
|
||||
agp_enable(dev->agp->agpdev, mode.mode);
|
||||
dev->agp->enabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_agp_mode mode;
|
||||
|
||||
mode = *(struct drm_agp_mode *) data;
|
||||
|
||||
return drm_agp_enable(dev, mode);
|
||||
}
|
||||
|
||||
int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
void *handle;
|
||||
unsigned long pages;
|
||||
u_int32_t type;
|
||||
struct agp_memory_info info;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
entry = malloc(sizeof(*entry), DRM_MEM_AGPLISTS, M_NOWAIT | M_ZERO);
|
||||
if (entry == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
type = (u_int32_t) request->type;
|
||||
|
||||
DRM_UNLOCK();
|
||||
handle = drm_agp_allocate_memory(pages, type);
|
||||
DRM_LOCK();
|
||||
if (handle == NULL) {
|
||||
free(entry, DRM_MEM_AGPLISTS);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
entry->handle = handle;
|
||||
entry->bound = 0;
|
||||
entry->pages = pages;
|
||||
entry->prev = NULL;
|
||||
entry->next = dev->agp->memory;
|
||||
if (dev->agp->memory)
|
||||
dev->agp->memory->prev = entry;
|
||||
dev->agp->memory = entry;
|
||||
|
||||
agp_memory_info(dev->agp->agpdev, entry->handle, &info);
|
||||
|
||||
request->handle = (unsigned long) entry->handle;
|
||||
request->physical = info.ami_physical;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_agp_buffer request;
|
||||
int retcode;
|
||||
|
||||
request = *(struct drm_agp_buffer *) data;
|
||||
|
||||
DRM_LOCK();
|
||||
retcode = drm_agp_alloc(dev, &request);
|
||||
DRM_UNLOCK();
|
||||
|
||||
*(struct drm_agp_buffer *) data = request;
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static drm_agp_mem_t * drm_agp_lookup_entry(struct drm_device *dev,
|
||||
void *handle)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
|
||||
for (entry = dev->agp->memory; entry; entry = entry->next) {
|
||||
if (entry->handle == handle) return entry;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
int retcode;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
entry = drm_agp_lookup_entry(dev, (void *)request->handle);
|
||||
if (entry == NULL || !entry->bound)
|
||||
return EINVAL;
|
||||
|
||||
DRM_UNLOCK();
|
||||
retcode = drm_agp_unbind_memory(entry->handle);
|
||||
DRM_LOCK();
|
||||
|
||||
if (retcode == 0)
|
||||
entry->bound = 0;
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_agp_binding request;
|
||||
int retcode;
|
||||
|
||||
request = *(struct drm_agp_binding *) data;
|
||||
|
||||
DRM_LOCK();
|
||||
retcode = drm_agp_unbind(dev, &request);
|
||||
DRM_UNLOCK();
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
int retcode;
|
||||
int page;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
DRM_DEBUG("agp_bind, page_size=%x\n", PAGE_SIZE);
|
||||
|
||||
entry = drm_agp_lookup_entry(dev, (void *)request->handle);
|
||||
if (entry == NULL || entry->bound)
|
||||
return EINVAL;
|
||||
|
||||
page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
DRM_UNLOCK();
|
||||
retcode = drm_agp_bind_memory(entry->handle, page);
|
||||
DRM_LOCK();
|
||||
if (retcode == 0)
|
||||
entry->bound = dev->agp->base + (page << PAGE_SHIFT);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_agp_binding request;
|
||||
int retcode;
|
||||
|
||||
request = *(struct drm_agp_binding *) data;
|
||||
|
||||
DRM_LOCK();
|
||||
retcode = drm_agp_bind(dev, &request);
|
||||
DRM_UNLOCK();
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
|
||||
{
|
||||
drm_agp_mem_t *entry;
|
||||
|
||||
if (!dev->agp || !dev->agp->acquired)
|
||||
return EINVAL;
|
||||
|
||||
entry = drm_agp_lookup_entry(dev, (void*)request->handle);
|
||||
if (entry == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (entry->prev)
|
||||
entry->prev->next = entry->next;
|
||||
else
|
||||
dev->agp->memory = entry->next;
|
||||
if (entry->next)
|
||||
entry->next->prev = entry->prev;
|
||||
|
||||
DRM_UNLOCK();
|
||||
if (entry->bound)
|
||||
drm_agp_unbind_memory(entry->handle);
|
||||
drm_agp_free_memory(entry->handle);
|
||||
DRM_LOCK();
|
||||
|
||||
free(entry, DRM_MEM_AGPLISTS);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int drm_agp_free_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_agp_buffer request;
|
||||
int retcode;
|
||||
|
||||
request = *(struct drm_agp_buffer *) data;
|
||||
|
||||
DRM_LOCK();
|
||||
retcode = drm_agp_free(dev, &request);
|
||||
DRM_UNLOCK();
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
drm_agp_head_t *drm_agp_init(void)
|
||||
{
|
||||
device_t agpdev;
|
||||
drm_agp_head_t *head = NULL;
|
||||
int agp_available = 1;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev)
|
||||
agp_available = 0;
|
||||
|
||||
DRM_DEBUG("agp_available = %d\n", agp_available);
|
||||
|
||||
if (agp_available) {
|
||||
head = malloc(sizeof(*head), DRM_MEM_AGPLISTS,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (head == NULL)
|
||||
return NULL;
|
||||
head->agpdev = agpdev;
|
||||
agp_get_info(agpdev, &head->info);
|
||||
head->base = head->info.ai_aperture_base;
|
||||
head->memory = NULL;
|
||||
DRM_INFO("AGP at 0x%08lx %dMB\n",
|
||||
(long)head->info.ai_aperture_base,
|
||||
(int)(head->info.ai_aperture_size >> 20));
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
void *drm_agp_allocate_memory(size_t pages, u32 type)
|
||||
{
|
||||
device_t agpdev;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev)
|
||||
return NULL;
|
||||
|
||||
return agp_alloc_memory(agpdev, type, pages << AGP_PAGE_SHIFT);
|
||||
}
|
||||
|
||||
int drm_agp_free_memory(void *handle)
|
||||
{
|
||||
device_t agpdev;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev || !handle)
|
||||
return 0;
|
||||
|
||||
agp_free_memory(agpdev, handle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int drm_agp_bind_memory(void *handle, off_t start)
|
||||
{
|
||||
device_t agpdev;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev || !handle)
|
||||
return EINVAL;
|
||||
|
||||
return agp_bind_memory(agpdev, handle, start * PAGE_SIZE);
|
||||
}
|
||||
|
||||
int drm_agp_unbind_memory(void *handle)
|
||||
{
|
||||
device_t agpdev;
|
||||
|
||||
agpdev = DRM_AGP_FIND_DEVICE();
|
||||
if (!agpdev || !handle)
|
||||
return EINVAL;
|
||||
|
||||
return agp_unbind_memory(agpdev, handle);
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
/**
|
||||
* \file drm_atomic.h
|
||||
* Atomic operations used in the DRM which may or may not be provided by the OS.
|
||||
*
|
||||
* \author Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright 2004 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Many of these implementations are rather fake, but good enough. */
|
||||
|
||||
typedef u_int32_t atomic_t;
|
||||
|
||||
#define atomic_set(p, v) (*(p) = (v))
|
||||
#define atomic_read(p) (*(p))
|
||||
#define atomic_inc(p) atomic_add_int(p, 1)
|
||||
#define atomic_dec(p) atomic_subtract_int(p, 1)
|
||||
#define atomic_add(n, p) atomic_add_int(p, n)
|
||||
#define atomic_sub(n, p) atomic_subtract_int(p, n)
|
||||
|
||||
static __inline atomic_t
|
||||
test_and_set_bit(int b, volatile void *p)
|
||||
{
|
||||
int s = splhigh();
|
||||
unsigned int m = 1<<b;
|
||||
unsigned int r = *(volatile int *)p & m;
|
||||
*(volatile int *)p |= m;
|
||||
splx(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
clear_bit(int b, volatile void *p)
|
||||
{
|
||||
atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
|
||||
}
|
||||
|
||||
static __inline void
|
||||
set_bit(int b, volatile void *p)
|
||||
{
|
||||
atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
test_bit(int b, volatile void *p)
|
||||
{
|
||||
return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
find_first_zero_bit(volatile void *p, int max)
|
||||
{
|
||||
int b;
|
||||
volatile int *ptr = (volatile int *)p;
|
||||
|
||||
for (b = 0; b < max; b += 32) {
|
||||
if (ptr[b >> 5] != ~0) {
|
||||
for (;;) {
|
||||
if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0)
|
||||
return b;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
|
@ -1,187 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_auth.c
|
||||
* Implementation of the get/authmagic ioctls implementing the authentication
|
||||
* scheme between the master and clients.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
static int drm_hash_magic(drm_magic_t magic)
|
||||
{
|
||||
return magic & (DRM_HASH_SIZE-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file private associated with the given magic number.
|
||||
*/
|
||||
static struct drm_file *drm_find_file(struct drm_device *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_magic_entry_t *pt;
|
||||
int hash = drm_hash_magic(magic);
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
return pt->priv;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given magic number into the hash table of used magic number
|
||||
* lists.
|
||||
*/
|
||||
static int drm_add_magic(struct drm_device *dev, struct drm_file *priv,
|
||||
drm_magic_t magic)
|
||||
{
|
||||
int hash;
|
||||
drm_magic_entry_t *entry;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
hash = drm_hash_magic(magic);
|
||||
entry = malloc(sizeof(*entry), DRM_MEM_MAGIC, M_ZERO | M_NOWAIT);
|
||||
if (!entry)
|
||||
return ENOMEM;
|
||||
entry->magic = magic;
|
||||
entry->priv = priv;
|
||||
entry->next = NULL;
|
||||
|
||||
if (dev->magiclist[hash].tail) {
|
||||
dev->magiclist[hash].tail->next = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
} else {
|
||||
dev->magiclist[hash].head = entry;
|
||||
dev->magiclist[hash].tail = entry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given magic number from the hash table of used magic number
|
||||
* lists.
|
||||
*/
|
||||
static int drm_remove_magic(struct drm_device *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_magic_entry_t *prev = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash;
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
hash = drm_hash_magic(magic);
|
||||
|
||||
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
if (dev->magiclist[hash].head == pt) {
|
||||
dev->magiclist[hash].head = pt->next;
|
||||
}
|
||||
if (dev->magiclist[hash].tail == pt) {
|
||||
dev->magiclist[hash].tail = prev;
|
||||
}
|
||||
if (prev) {
|
||||
prev->next = pt->next;
|
||||
}
|
||||
free(pt, DRM_MEM_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the client, this returns a unique magic number to be authorized
|
||||
* by the master.
|
||||
*
|
||||
* The master may use its own knowledge of the client (such as the X
|
||||
* connection that the magic is passed over) to determine if the magic number
|
||||
* should be authenticated.
|
||||
*/
|
||||
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
static drm_magic_t sequence = 0;
|
||||
struct drm_auth *auth = data;
|
||||
|
||||
/* Find unique magic */
|
||||
if (file_priv->magic) {
|
||||
auth->magic = file_priv->magic;
|
||||
} else {
|
||||
DRM_LOCK();
|
||||
do {
|
||||
int old = sequence;
|
||||
|
||||
auth->magic = old+1;
|
||||
|
||||
if (!atomic_cmpset_int(&sequence, old, auth->magic))
|
||||
continue;
|
||||
} while (drm_find_file(dev, auth->magic));
|
||||
file_priv->magic = auth->magic;
|
||||
drm_add_magic(dev, file_priv, auth->magic);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
DRM_DEBUG("%u\n", auth->magic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the client associated with the given magic number as authenticated.
|
||||
*/
|
||||
int drm_authmagic(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_auth *auth = data;
|
||||
struct drm_file *priv;
|
||||
|
||||
DRM_DEBUG("%u\n", auth->magic);
|
||||
|
||||
DRM_LOCK();
|
||||
priv = drm_find_file(dev, auth->magic);
|
||||
if (priv != NULL) {
|
||||
priv->authenticated = 1;
|
||||
drm_remove_magic(dev, auth->magic);
|
||||
DRM_UNLOCK();
|
||||
return 0;
|
||||
} else {
|
||||
DRM_UNLOCK();
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
1110
bsd-core/drm_bufs.c
1110
bsd-core/drm_bufs.c
File diff suppressed because it is too large
Load Diff
|
@ -1,320 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_context.c
|
||||
* Implementation of the context management ioctls.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/* ================================================================
|
||||
* Context bitmap support
|
||||
*/
|
||||
|
||||
void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle)
|
||||
{
|
||||
if (ctx_handle < 0 || ctx_handle >= DRM_MAX_CTXBITMAP ||
|
||||
dev->ctx_bitmap == NULL) {
|
||||
DRM_ERROR("Attempt to free invalid context handle: %d\n",
|
||||
ctx_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_LOCK();
|
||||
clear_bit(ctx_handle, dev->ctx_bitmap);
|
||||
dev->context_sareas[ctx_handle] = NULL;
|
||||
DRM_UNLOCK();
|
||||
return;
|
||||
}
|
||||
|
||||
int drm_ctxbitmap_next(struct drm_device *dev)
|
||||
{
|
||||
int bit;
|
||||
|
||||
if (dev->ctx_bitmap == NULL)
|
||||
return -1;
|
||||
|
||||
DRM_LOCK();
|
||||
bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
|
||||
if (bit >= DRM_MAX_CTXBITMAP) {
|
||||
DRM_UNLOCK();
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_bit(bit, dev->ctx_bitmap);
|
||||
DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
|
||||
if ((bit+1) > dev->max_context) {
|
||||
dev->max_context = (bit+1);
|
||||
if (dev->context_sareas != NULL) {
|
||||
drm_local_map_t **ctx_sareas;
|
||||
|
||||
ctx_sareas = realloc(dev->context_sareas,
|
||||
dev->max_context * sizeof(*dev->context_sareas),
|
||||
DRM_MEM_SAREA, M_NOWAIT);
|
||||
if (ctx_sareas == NULL) {
|
||||
clear_bit(bit, dev->ctx_bitmap);
|
||||
DRM_UNLOCK();
|
||||
return -1;
|
||||
}
|
||||
dev->context_sareas = ctx_sareas;
|
||||
dev->context_sareas[bit] = NULL;
|
||||
} else {
|
||||
/* max_context == 1 at this point */
|
||||
dev->context_sareas = malloc(dev->max_context *
|
||||
sizeof(*dev->context_sareas), DRM_MEM_SAREA,
|
||||
M_NOWAIT);
|
||||
if (dev->context_sareas == NULL) {
|
||||
clear_bit(bit, dev->ctx_bitmap);
|
||||
DRM_UNLOCK();
|
||||
return -1;
|
||||
}
|
||||
dev->context_sareas[bit] = NULL;
|
||||
}
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
return bit;
|
||||
}
|
||||
|
||||
int drm_ctxbitmap_init(struct drm_device *dev)
|
||||
{
|
||||
int i;
|
||||
int temp;
|
||||
|
||||
DRM_LOCK();
|
||||
dev->ctx_bitmap = malloc(PAGE_SIZE, DRM_MEM_CTXBITMAP,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (dev->ctx_bitmap == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return ENOMEM;
|
||||
}
|
||||
dev->context_sareas = NULL;
|
||||
dev->max_context = -1;
|
||||
DRM_UNLOCK();
|
||||
|
||||
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
|
||||
temp = drm_ctxbitmap_next(dev);
|
||||
DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drm_ctxbitmap_cleanup(struct drm_device *dev)
|
||||
{
|
||||
DRM_LOCK();
|
||||
if (dev->context_sareas != NULL)
|
||||
free(dev->context_sareas, DRM_MEM_SAREA);
|
||||
free(dev->ctx_bitmap, DRM_MEM_CTXBITMAP);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Per Context SAREA Support
|
||||
*/
|
||||
|
||||
int drm_getsareactx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx_priv_map *request = data;
|
||||
drm_local_map_t *map;
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->max_context < 0 ||
|
||||
request->ctx_id >= (unsigned) dev->max_context) {
|
||||
DRM_UNLOCK();
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
map = dev->context_sareas[request->ctx_id];
|
||||
DRM_UNLOCK();
|
||||
|
||||
request->handle = map->handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_setsareactx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx_priv_map *request = data;
|
||||
drm_local_map_t *map = NULL;
|
||||
|
||||
DRM_LOCK();
|
||||
TAILQ_FOREACH(map, &dev->maplist, link) {
|
||||
if (map->handle == request->handle) {
|
||||
if (dev->max_context < 0)
|
||||
goto bad;
|
||||
if (request->ctx_id >= (unsigned) dev->max_context)
|
||||
goto bad;
|
||||
dev->context_sareas[request->ctx_id] = map;
|
||||
DRM_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bad:
|
||||
DRM_UNLOCK();
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* The actual DRM context handling routines
|
||||
*/
|
||||
|
||||
int drm_context_switch(struct drm_device *dev, int old, int new)
|
||||
{
|
||||
if (test_and_set_bit(0, &dev->context_flag)) {
|
||||
DRM_ERROR("Reentering -- FIXME\n");
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
DRM_DEBUG("Context switch from %d to %d\n", old, new);
|
||||
|
||||
if (new == dev->last_context) {
|
||||
clear_bit(0, &dev->context_flag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_context_switch_complete(struct drm_device *dev, int new)
|
||||
{
|
||||
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
|
||||
|
||||
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
|
||||
DRM_ERROR("Lock isn't held after context switch\n");
|
||||
}
|
||||
|
||||
/* If a context switch is ever initiated
|
||||
when the kernel holds the lock, release
|
||||
that lock here. */
|
||||
clear_bit(0, &dev->context_flag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx_res *res = data;
|
||||
struct drm_ctx ctx;
|
||||
int i;
|
||||
|
||||
if (res->count >= DRM_RESERVED_CONTEXTS) {
|
||||
bzero(&ctx, sizeof(ctx));
|
||||
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
|
||||
ctx.handle = i;
|
||||
if (DRM_COPY_TO_USER(&res->contexts[i],
|
||||
&ctx, sizeof(ctx)))
|
||||
return EFAULT;
|
||||
}
|
||||
}
|
||||
res->count = DRM_RESERVED_CONTEXTS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx *ctx = data;
|
||||
|
||||
ctx->handle = drm_ctxbitmap_next(dev);
|
||||
if (ctx->handle == DRM_KERNEL_CONTEXT) {
|
||||
/* Skip kernel's context and get a new one. */
|
||||
ctx->handle = drm_ctxbitmap_next(dev);
|
||||
}
|
||||
DRM_DEBUG("%d\n", ctx->handle);
|
||||
if (ctx->handle == -1) {
|
||||
DRM_DEBUG("Not enough free contexts.\n");
|
||||
/* Should this return -EBUSY instead? */
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (dev->driver->context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
|
||||
DRM_LOCK();
|
||||
dev->driver->context_ctor(dev, ctx->handle);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
/* This does nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx *ctx = data;
|
||||
|
||||
/* This is 0, because we don't handle any context flags */
|
||||
ctx->flags = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_switchctx(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx *ctx = data;
|
||||
|
||||
DRM_DEBUG("%d\n", ctx->handle);
|
||||
return drm_context_switch(dev, dev->last_context, ctx->handle);
|
||||
}
|
||||
|
||||
int drm_newctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx *ctx = data;
|
||||
|
||||
DRM_DEBUG("%d\n", ctx->handle);
|
||||
drm_context_switch_complete(dev, ctx->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_rmctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_ctx *ctx = data;
|
||||
|
||||
DRM_DEBUG("%d\n", ctx->handle);
|
||||
if (ctx->handle != DRM_KERNEL_CONTEXT) {
|
||||
if (dev->driver->context_dtor) {
|
||||
DRM_LOCK();
|
||||
dev->driver->context_dtor(dev, ctx->handle);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
drm_ctxbitmap_free(dev, ctx->handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_dma.c
|
||||
* Support code for DMA buffer management.
|
||||
*
|
||||
* The implementation used to be significantly more complicated, but the
|
||||
* complexity has been moved into the drivers as different buffer management
|
||||
* schemes evolved.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
int drm_dma_setup(struct drm_device *dev)
|
||||
{
|
||||
|
||||
dev->dma = malloc(sizeof(*dev->dma), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
|
||||
if (dev->dma == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
DRM_SPININIT(&dev->dma_lock, "drmdma");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drm_dma_takedown(struct drm_device *dev)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i, j;
|
||||
|
||||
if (dma == NULL)
|
||||
return;
|
||||
|
||||
/* Clear dma buffers */
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
if (dma->bufs[i].seg_count) {
|
||||
DRM_DEBUG("order %d: buf_count = %d,"
|
||||
" seg_count = %d\n", i, dma->bufs[i].buf_count,
|
||||
dma->bufs[i].seg_count);
|
||||
for (j = 0; j < dma->bufs[i].seg_count; j++) {
|
||||
drm_pci_free(dev, dma->bufs[i].seglist[j]);
|
||||
}
|
||||
free(dma->bufs[i].seglist, DRM_MEM_SEGS);
|
||||
}
|
||||
|
||||
if (dma->bufs[i].buf_count) {
|
||||
for (j = 0; j < dma->bufs[i].buf_count; j++) {
|
||||
free(dma->bufs[i].buflist[j].dev_private,
|
||||
DRM_MEM_BUFS);
|
||||
}
|
||||
free(dma->bufs[i].buflist, DRM_MEM_BUFS);
|
||||
}
|
||||
}
|
||||
|
||||
free(dma->buflist, DRM_MEM_BUFS);
|
||||
free(dma->pagelist, DRM_MEM_PAGES);
|
||||
free(dev->dma, DRM_MEM_DRIVER);
|
||||
dev->dma = NULL;
|
||||
DRM_SPINUNINIT(&dev->dma_lock);
|
||||
}
|
||||
|
||||
|
||||
void drm_free_buffer(struct drm_device *dev, drm_buf_t *buf)
|
||||
{
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
buf->pending = 0;
|
||||
buf->file_priv= NULL;
|
||||
buf->used = 0;
|
||||
}
|
||||
|
||||
void drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int i;
|
||||
|
||||
if (!dma)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (dma->buflist[i]->file_priv == file_priv) {
|
||||
switch (dma->buflist[i]->list) {
|
||||
case DRM_LIST_NONE:
|
||||
drm_free_buffer(dev, dma->buflist[i]);
|
||||
break;
|
||||
case DRM_LIST_WAIT:
|
||||
dma->buflist[i]->list = DRM_LIST_RECLAIM;
|
||||
break;
|
||||
default:
|
||||
/* Buffer already on hardware. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Call into the driver-specific DMA handler */
|
||||
int drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
|
||||
if (dev->driver->dma_ioctl) {
|
||||
/* shared code returns -errno */
|
||||
return -dev->driver->dma_ioctl(dev, data, file_priv);
|
||||
} else {
|
||||
DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_drawable.c
|
||||
* This file implements ioctls to store information along with DRM drawables,
|
||||
* such as the current set of cliprects for vblank-synced buffer swaps.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
struct bsd_drm_drawable_info {
|
||||
struct drm_drawable_info info;
|
||||
int handle;
|
||||
RB_ENTRY(bsd_drm_drawable_info) tree;
|
||||
};
|
||||
|
||||
static int
|
||||
drm_drawable_compare(struct bsd_drm_drawable_info *a,
|
||||
struct bsd_drm_drawable_info *b)
|
||||
{
|
||||
if (a->handle > b->handle)
|
||||
return 1;
|
||||
if (a->handle < b->handle)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
RB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree,
|
||||
drm_drawable_compare);
|
||||
|
||||
struct drm_drawable_info *
|
||||
drm_get_drawable_info(struct drm_device *dev, int handle)
|
||||
{
|
||||
struct bsd_drm_drawable_info find, *result;
|
||||
|
||||
find.handle = handle;
|
||||
result = RB_FIND(drawable_tree, &dev->drw_head, &find);
|
||||
|
||||
return &result->info;
|
||||
}
|
||||
|
||||
int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_draw *draw = data;
|
||||
struct bsd_drm_drawable_info *info;
|
||||
|
||||
info = malloc(sizeof(struct bsd_drm_drawable_info), DRM_MEM_DRAWABLE,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (info == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
info->handle = alloc_unr(dev->drw_unrhdr);
|
||||
DRM_SPINLOCK(&dev->drw_lock);
|
||||
RB_INSERT(drawable_tree, &dev->drw_head, info);
|
||||
draw->handle = info->handle;
|
||||
DRM_SPINUNLOCK(&dev->drw_lock);
|
||||
|
||||
DRM_DEBUG("%d\n", draw->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_draw *draw = (struct drm_draw *)data;
|
||||
struct drm_drawable_info *info;
|
||||
|
||||
DRM_SPINLOCK(&dev->drw_lock);
|
||||
info = drm_get_drawable_info(dev, draw->handle);
|
||||
if (info != NULL) {
|
||||
RB_REMOVE(drawable_tree, &dev->drw_head,
|
||||
(struct bsd_drm_drawable_info *)info);
|
||||
DRM_SPINUNLOCK(&dev->drw_lock);
|
||||
free_unr(dev->drw_unrhdr, draw->handle);
|
||||
free(info->rects, DRM_MEM_DRAWABLE);
|
||||
free(info, DRM_MEM_DRAWABLE);
|
||||
return 0;
|
||||
} else {
|
||||
DRM_SPINUNLOCK(&dev->drw_lock);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int drm_update_draw(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_drawable_info *info;
|
||||
struct drm_update_draw *update = (struct drm_update_draw *)data;
|
||||
int ret;
|
||||
|
||||
info = drm_get_drawable_info(dev, update->handle);
|
||||
if (info == NULL)
|
||||
return EINVAL;
|
||||
|
||||
switch (update->type) {
|
||||
case DRM_DRAWABLE_CLIPRECTS:
|
||||
DRM_SPINLOCK(&dev->drw_lock);
|
||||
if (update->num != info->num_rects) {
|
||||
free(info->rects, DRM_MEM_DRAWABLE);
|
||||
info->rects = NULL;
|
||||
info->num_rects = 0;
|
||||
}
|
||||
if (update->num == 0) {
|
||||
DRM_SPINUNLOCK(&dev->drw_lock);
|
||||
return 0;
|
||||
}
|
||||
if (info->rects == NULL) {
|
||||
info->rects = malloc(sizeof(*info->rects) *
|
||||
update->num, DRM_MEM_DRAWABLE, M_NOWAIT);
|
||||
if (info->rects == NULL) {
|
||||
DRM_SPINUNLOCK(&dev->drw_lock);
|
||||
return ENOMEM;
|
||||
}
|
||||
info->num_rects = update->num;
|
||||
}
|
||||
/* For some reason the pointer arg is unsigned long long. */
|
||||
ret = copyin((void *)(intptr_t)update->data, info->rects,
|
||||
sizeof(*info->rects) * info->num_rects);
|
||||
DRM_SPINUNLOCK(&dev->drw_lock);
|
||||
return ret;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void drm_drawable_free_all(struct drm_device *dev)
|
||||
{
|
||||
struct bsd_drm_drawable_info *info, *next;
|
||||
|
||||
DRM_SPINLOCK(&dev->drw_lock);
|
||||
for (info = RB_MIN(drawable_tree, &dev->drw_head);
|
||||
info != NULL ; info = next) {
|
||||
next = RB_NEXT(drawable_tree, &dev->drw_head, info);
|
||||
RB_REMOVE(drawable_tree, &dev->drw_head,
|
||||
(struct bsd_drm_drawable_info *)info);
|
||||
DRM_SPINUNLOCK(&dev->drw_lock);
|
||||
free_unr(dev->drw_unrhdr, info->handle);
|
||||
free(info->info.rects, DRM_MEM_DRAWABLE);
|
||||
free(info, DRM_MEM_DRAWABLE);
|
||||
DRM_SPINLOCK(&dev->drw_lock);
|
||||
}
|
||||
DRM_SPINUNLOCK(&dev->drw_lock);
|
||||
}
|
|
@ -1,839 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_drv.c
|
||||
* The catch-all file for DRM device support, including module setup/teardown,
|
||||
* open/close, and ioctl dispatch.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/limits.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_sarea.h"
|
||||
|
||||
#ifdef DRM_DEBUG_DEFAULT_ON
|
||||
int drm_debug_flag = 1;
|
||||
#else
|
||||
int drm_debug_flag = 0;
|
||||
#endif
|
||||
|
||||
static int drm_load(struct drm_device *dev);
|
||||
static void drm_unload(struct drm_device *dev);
|
||||
static drm_pci_id_list_t *drm_find_description(int vendor, int device,
|
||||
drm_pci_id_list_t *idlist);
|
||||
|
||||
#define DRIVER_SOFTC(unit) \
|
||||
((struct drm_device *)devclass_get_softc(drm_devclass, unit))
|
||||
|
||||
MODULE_VERSION(drm, 1);
|
||||
MODULE_DEPEND(drm, agp, 1, 1, 1);
|
||||
MODULE_DEPEND(drm, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(drm, mem, 1, 1, 1);
|
||||
|
||||
static drm_ioctl_desc_t drm_ioctls[256] = {
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
};
|
||||
|
||||
static struct cdevsw drm_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = drm_open,
|
||||
.d_read = drm_read,
|
||||
.d_ioctl = drm_ioctl,
|
||||
.d_poll = drm_poll,
|
||||
.d_mmap = drm_mmap,
|
||||
.d_name = "drm",
|
||||
.d_flags = D_TRACKCLOSE
|
||||
};
|
||||
|
||||
int drm_msi = 1; /* Enable by default. */
|
||||
TUNABLE_INT("hw.drm.msi", &drm_msi);
|
||||
|
||||
static struct drm_msi_blacklist_entry drm_msi_blacklist[] = {
|
||||
{0x8086, 0x2772}, /* Intel i945G */ \
|
||||
{0x8086, 0x27A2}, /* Intel i945GM */ \
|
||||
{0x8086, 0x27AE}, /* Intel i945GME */ \
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static int drm_msi_is_blacklisted(int vendor, int device)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; drm_msi_blacklist[i].vendor != 0; i++) {
|
||||
if ((drm_msi_blacklist[i].vendor == vendor) &&
|
||||
(drm_msi_blacklist[i].device == device)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_probe(device_t kdev, drm_pci_id_list_t *idlist)
|
||||
{
|
||||
drm_pci_id_list_t *id_entry;
|
||||
int vendor, device;
|
||||
#if __FreeBSD_version < 700010
|
||||
device_t realdev;
|
||||
|
||||
if (!strcmp(device_get_name(kdev), "drmsub"))
|
||||
realdev = device_get_parent(kdev);
|
||||
else
|
||||
realdev = kdev;
|
||||
vendor = pci_get_vendor(realdev);
|
||||
device = pci_get_device(realdev);
|
||||
#else
|
||||
vendor = pci_get_vendor(kdev);
|
||||
device = pci_get_device(kdev);
|
||||
#endif
|
||||
|
||||
if (pci_get_class(kdev) != PCIC_DISPLAY
|
||||
|| pci_get_subclass(kdev) != PCIS_DISPLAY_VGA)
|
||||
return ENXIO;
|
||||
|
||||
id_entry = drm_find_description(vendor, device, idlist);
|
||||
if (id_entry != NULL) {
|
||||
if (!device_get_desc(kdev)) {
|
||||
DRM_DEBUG("desc : %s\n", device_get_desc(kdev));
|
||||
device_set_desc(kdev, id_entry->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
int drm_attach(device_t kdev, drm_pci_id_list_t *idlist)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
drm_pci_id_list_t *id_entry;
|
||||
int unit, msicount;
|
||||
|
||||
unit = device_get_unit(kdev);
|
||||
dev = device_get_softc(kdev);
|
||||
|
||||
#if __FreeBSD_version < 700010
|
||||
if (!strcmp(device_get_name(kdev), "drmsub"))
|
||||
dev->device = device_get_parent(kdev);
|
||||
else
|
||||
dev->device = kdev;
|
||||
#else
|
||||
dev->device = kdev;
|
||||
#endif
|
||||
dev->devnode = make_dev(&drm_cdevsw,
|
||||
unit,
|
||||
DRM_DEV_UID,
|
||||
DRM_DEV_GID,
|
||||
DRM_DEV_MODE,
|
||||
"dri/card%d", unit);
|
||||
|
||||
#if __FreeBSD_version >= 700053
|
||||
dev->pci_domain = pci_get_domain(dev->device);
|
||||
#else
|
||||
dev->pci_domain = 0;
|
||||
#endif
|
||||
dev->pci_bus = pci_get_bus(dev->device);
|
||||
dev->pci_slot = pci_get_slot(dev->device);
|
||||
dev->pci_func = pci_get_function(dev->device);
|
||||
|
||||
dev->pci_vendor = pci_get_vendor(dev->device);
|
||||
dev->pci_device = pci_get_device(dev->device);
|
||||
|
||||
if (drm_msi &&
|
||||
!drm_msi_is_blacklisted(dev->pci_vendor, dev->pci_device)) {
|
||||
msicount = pci_msi_count(dev->device);
|
||||
DRM_DEBUG("MSI count = %d\n", msicount);
|
||||
if (msicount > 1)
|
||||
msicount = 1;
|
||||
|
||||
if (pci_alloc_msi(dev->device, &msicount) == 0) {
|
||||
DRM_INFO("MSI enabled %d message(s)\n", msicount);
|
||||
dev->msi_enabled = 1;
|
||||
dev->irqrid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ,
|
||||
&dev->irqrid, RF_SHAREABLE);
|
||||
if (!dev->irqr) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
dev->irq = (int) rman_get_start(dev->irqr);
|
||||
|
||||
mtx_init(&dev->dev_lock, "drmdev", NULL, MTX_DEF);
|
||||
mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF);
|
||||
mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF);
|
||||
mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF);
|
||||
|
||||
id_entry = drm_find_description(dev->pci_vendor,
|
||||
dev->pci_device, idlist);
|
||||
dev->id_entry = id_entry;
|
||||
|
||||
return drm_load(dev);
|
||||
}
|
||||
|
||||
int drm_detach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
|
||||
dev = device_get_softc(kdev);
|
||||
|
||||
drm_unload(dev);
|
||||
|
||||
bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
|
||||
|
||||
if (dev->msi_enabled) {
|
||||
pci_release_msi(dev->device);
|
||||
DRM_INFO("MSI released\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DRM_DEV_NAME
|
||||
#define DRM_DEV_NAME "drm"
|
||||
#endif
|
||||
|
||||
devclass_t drm_devclass;
|
||||
|
||||
drm_pci_id_list_t *drm_find_description(int vendor, int device,
|
||||
drm_pci_id_list_t *idlist)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; idlist[i].vendor != 0; i++) {
|
||||
if ((idlist[i].vendor == vendor) &&
|
||||
((idlist[i].device == device) ||
|
||||
(idlist[i].device == 0))) {
|
||||
return &idlist[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int drm_firstopen(struct drm_device *dev)
|
||||
{
|
||||
drm_local_map_t *map;
|
||||
int i;
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
/* prebuild the SAREA */
|
||||
i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
|
||||
_DRM_CONTAINS_LOCK, &map);
|
||||
if (i != 0)
|
||||
return i;
|
||||
|
||||
if (dev->driver->firstopen)
|
||||
dev->driver->firstopen(dev);
|
||||
|
||||
dev->buf_use = 0;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
|
||||
i = drm_dma_setup(dev);
|
||||
if (i != 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
||||
dev->magiclist[i].head = NULL;
|
||||
dev->magiclist[i].tail = NULL;
|
||||
}
|
||||
|
||||
dev->lock.lock_queue = 0;
|
||||
dev->irq_enabled = 0;
|
||||
dev->context_flag = 0;
|
||||
dev->last_context = 0;
|
||||
dev->if_version = 0;
|
||||
|
||||
dev->buf_sigio = NULL;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_lastclose(struct drm_device *dev)
|
||||
{
|
||||
drm_magic_entry_t *pt, *next;
|
||||
drm_local_map_t *map, *mapsave;
|
||||
int i;
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (dev->driver->lastclose != NULL)
|
||||
dev->driver->lastclose(dev);
|
||||
|
||||
if (dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
if (dev->unique) {
|
||||
free(dev->unique, DRM_MEM_DRIVER);
|
||||
dev->unique = NULL;
|
||||
dev->unique_len = 0;
|
||||
}
|
||||
/* Clear pid list */
|
||||
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
||||
for (pt = dev->magiclist[i].head; pt; pt = next) {
|
||||
next = pt->next;
|
||||
free(pt, DRM_MEM_MAGIC);
|
||||
}
|
||||
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
|
||||
}
|
||||
|
||||
DRM_UNLOCK();
|
||||
drm_drawable_free_all(dev);
|
||||
DRM_LOCK();
|
||||
|
||||
/* Clear AGP information */
|
||||
if (dev->agp) {
|
||||
drm_agp_mem_t *entry;
|
||||
drm_agp_mem_t *nexte;
|
||||
|
||||
/* Remove AGP resources, but leave dev->agp intact until
|
||||
* drm_unload is called.
|
||||
*/
|
||||
for (entry = dev->agp->memory; entry; entry = nexte) {
|
||||
nexte = entry->next;
|
||||
if (entry->bound)
|
||||
drm_agp_unbind_memory(entry->handle);
|
||||
drm_agp_free_memory(entry->handle);
|
||||
free(entry, DRM_MEM_AGPLISTS);
|
||||
}
|
||||
dev->agp->memory = NULL;
|
||||
|
||||
if (dev->agp->acquired)
|
||||
drm_agp_release(dev);
|
||||
|
||||
dev->agp->acquired = 0;
|
||||
dev->agp->enabled = 0;
|
||||
}
|
||||
if (dev->sg != NULL) {
|
||||
drm_sg_cleanup(dev->sg);
|
||||
dev->sg = NULL;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
|
||||
if (!(map->flags & _DRM_DRIVER))
|
||||
drm_rmmap(dev, map);
|
||||
}
|
||||
|
||||
drm_dma_takedown(dev);
|
||||
if (dev->lock.hw_lock) {
|
||||
dev->lock.hw_lock = NULL; /* SHM removed */
|
||||
dev->lock.file_priv = NULL;
|
||||
DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_load(struct drm_device *dev)
|
||||
{
|
||||
int i, retcode;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
TAILQ_INIT(&dev->maplist);
|
||||
|
||||
drm_mem_init();
|
||||
drm_sysctl_init(dev);
|
||||
TAILQ_INIT(&dev->files);
|
||||
|
||||
dev->counters = 6;
|
||||
dev->types[0] = _DRM_STAT_LOCK;
|
||||
dev->types[1] = _DRM_STAT_OPENS;
|
||||
dev->types[2] = _DRM_STAT_CLOSES;
|
||||
dev->types[3] = _DRM_STAT_IOCTLS;
|
||||
dev->types[4] = _DRM_STAT_LOCKS;
|
||||
dev->types[5] = _DRM_STAT_UNLOCKS;
|
||||
|
||||
for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
|
||||
atomic_set(&dev->counts[i], 0);
|
||||
|
||||
if (dev->driver->load != NULL) {
|
||||
DRM_LOCK();
|
||||
/* Shared code returns -errno. */
|
||||
retcode = -dev->driver->load(dev,
|
||||
dev->id_entry->driver_private);
|
||||
if (pci_enable_busmaster(dev->device))
|
||||
DRM_ERROR("Request to enable bus-master failed.\n");
|
||||
DRM_UNLOCK();
|
||||
if (retcode != 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (drm_core_has_AGP(dev)) {
|
||||
if (drm_device_is_agp(dev))
|
||||
dev->agp = drm_agp_init();
|
||||
if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) &&
|
||||
dev->agp == NULL) {
|
||||
DRM_ERROR("Card isn't AGP, or couldn't initialize "
|
||||
"AGP.\n");
|
||||
retcode = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
if (dev->agp != NULL) {
|
||||
if (drm_mtrr_add(dev->agp->info.ai_aperture_base,
|
||||
dev->agp->info.ai_aperture_size, DRM_MTRR_WC) == 0)
|
||||
dev->agp->mtrr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
retcode = drm_ctxbitmap_init(dev);
|
||||
if (retcode != 0) {
|
||||
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL);
|
||||
if (dev->drw_unrhdr == NULL) {
|
||||
DRM_ERROR("Couldn't allocate drawable number allocator\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s\n",
|
||||
dev->driver->name,
|
||||
dev->driver->major,
|
||||
dev->driver->minor,
|
||||
dev->driver->patchlevel,
|
||||
dev->driver->date);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
drm_sysctl_cleanup(dev);
|
||||
DRM_LOCK();
|
||||
drm_lastclose(dev);
|
||||
DRM_UNLOCK();
|
||||
destroy_dev(dev->devnode);
|
||||
|
||||
mtx_destroy(&dev->drw_lock);
|
||||
mtx_destroy(&dev->vbl_lock);
|
||||
mtx_destroy(&dev->irq_lock);
|
||||
mtx_destroy(&dev->dev_lock);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static void drm_unload(struct drm_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
drm_sysctl_cleanup(dev);
|
||||
destroy_dev(dev->devnode);
|
||||
|
||||
drm_ctxbitmap_cleanup(dev);
|
||||
|
||||
if (dev->agp && dev->agp->mtrr) {
|
||||
int __unused retcode;
|
||||
|
||||
retcode = drm_mtrr_del(0, dev->agp->info.ai_aperture_base,
|
||||
dev->agp->info.ai_aperture_size, DRM_MTRR_WC);
|
||||
DRM_DEBUG("mtrr_del = %d", retcode);
|
||||
}
|
||||
|
||||
DRM_LOCK();
|
||||
drm_lastclose(dev);
|
||||
DRM_UNLOCK();
|
||||
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
/* Clean up PCI resources allocated by drm_bufs.c. We're not really
|
||||
* worried about resource consumption while the DRM is inactive (between
|
||||
* lastclose and firstopen or unload) because these aren't actually
|
||||
* taking up KVA, just keeping the PCI resource allocated.
|
||||
*/
|
||||
for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
|
||||
if (dev->pcir[i] == NULL)
|
||||
continue;
|
||||
bus_release_resource(dev->device, SYS_RES_MEMORY,
|
||||
dev->pcirid[i], dev->pcir[i]);
|
||||
dev->pcir[i] = NULL;
|
||||
}
|
||||
|
||||
if (dev->agp) {
|
||||
free(dev->agp, DRM_MEM_AGPLISTS);
|
||||
dev->agp = NULL;
|
||||
}
|
||||
|
||||
if (dev->driver->unload != NULL) {
|
||||
DRM_LOCK();
|
||||
dev->driver->unload(dev);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
delete_unrhdr(dev->drw_unrhdr);
|
||||
|
||||
drm_mem_uninit();
|
||||
|
||||
if (pci_disable_busmaster(dev->device))
|
||||
DRM_ERROR("Request to disable bus-master failed.\n");
|
||||
|
||||
mtx_destroy(&dev->drw_lock);
|
||||
mtx_destroy(&dev->vbl_lock);
|
||||
mtx_destroy(&dev->irq_lock);
|
||||
mtx_destroy(&dev->dev_lock);
|
||||
}
|
||||
|
||||
int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_version *version = data;
|
||||
int len;
|
||||
|
||||
#define DRM_COPY( name, value ) \
|
||||
len = strlen( value ); \
|
||||
if ( len > name##_len ) len = name##_len; \
|
||||
name##_len = strlen( value ); \
|
||||
if ( len && name ) { \
|
||||
if ( DRM_COPY_TO_USER( name, value, len ) ) \
|
||||
return EFAULT; \
|
||||
}
|
||||
|
||||
version->version_major = dev->driver->major;
|
||||
version->version_minor = dev->driver->minor;
|
||||
version->version_patchlevel = dev->driver->patchlevel;
|
||||
|
||||
DRM_COPY(version->name, dev->driver->name);
|
||||
DRM_COPY(version->date, dev->driver->date);
|
||||
DRM_COPY(version->desc, dev->driver->desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
|
||||
{
|
||||
struct drm_device *dev = NULL;
|
||||
int retcode = 0;
|
||||
|
||||
dev = DRIVER_SOFTC(dev2unit(kdev));
|
||||
|
||||
DRM_DEBUG("open_count = %d\n", dev->open_count);
|
||||
|
||||
retcode = drm_open_helper(kdev, flags, fmt, p, dev);
|
||||
|
||||
if (!retcode) {
|
||||
atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
|
||||
DRM_LOCK();
|
||||
device_busy(dev->device);
|
||||
if (!dev->open_count++)
|
||||
retcode = drm_firstopen(dev);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
void drm_close(void *data)
|
||||
{
|
||||
struct drm_file *file_priv = data;
|
||||
struct drm_device *dev = file_priv->dev;
|
||||
int retcode = 0;
|
||||
|
||||
DRM_DEBUG("open_count = %d\n", dev->open_count);
|
||||
|
||||
DRM_LOCK();
|
||||
|
||||
if (dev->driver->preclose != NULL)
|
||||
dev->driver->preclose(dev, file_priv);
|
||||
|
||||
/* ========================================================
|
||||
* Begin inline drm_release
|
||||
*/
|
||||
|
||||
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
|
||||
DRM_CURRENTPID, (long)dev->device, dev->open_count);
|
||||
|
||||
if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
|
||||
&& dev->lock.file_priv == file_priv) {
|
||||
DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
|
||||
DRM_CURRENTPID,
|
||||
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
|
||||
if (dev->driver->reclaim_buffers_locked != NULL)
|
||||
dev->driver->reclaim_buffers_locked(dev, file_priv);
|
||||
|
||||
drm_lock_free(&dev->lock,
|
||||
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
|
||||
|
||||
/* FIXME: may require heavy-handed reset of
|
||||
hardware at this point, possibly
|
||||
processed via a callback to the X
|
||||
server. */
|
||||
} else if (dev->driver->reclaim_buffers_locked != NULL &&
|
||||
dev->lock.hw_lock != NULL) {
|
||||
/* The lock is required to reclaim buffers */
|
||||
for (;;) {
|
||||
if (!dev->lock.hw_lock) {
|
||||
/* Device has been unregistered */
|
||||
retcode = EINTR;
|
||||
break;
|
||||
}
|
||||
if (drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) {
|
||||
dev->lock.file_priv = file_priv;
|
||||
dev->lock.lock_time = jiffies;
|
||||
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
|
||||
break; /* Got lock */
|
||||
}
|
||||
/* Contention */
|
||||
retcode = mtx_sleep((void *)&dev->lock.lock_queue,
|
||||
&dev->dev_lock, PCATCH, "drmlk2", 0);
|
||||
if (retcode)
|
||||
break;
|
||||
}
|
||||
if (retcode == 0) {
|
||||
dev->driver->reclaim_buffers_locked(dev, file_priv);
|
||||
drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
|
||||
!dev->driver->reclaim_buffers_locked)
|
||||
drm_reclaim_buffers(dev, file_priv);
|
||||
|
||||
funsetown(&dev->buf_sigio);
|
||||
|
||||
if (dev->driver->postclose != NULL)
|
||||
dev->driver->postclose(dev, file_priv);
|
||||
TAILQ_REMOVE(&dev->files, file_priv, link);
|
||||
free(file_priv, DRM_MEM_FILES);
|
||||
|
||||
/* ========================================================
|
||||
* End inline drm_release
|
||||
*/
|
||||
|
||||
atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
|
||||
device_unbusy(dev->device);
|
||||
if (--dev->open_count == 0) {
|
||||
retcode = drm_lastclose(dev);
|
||||
}
|
||||
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.
|
||||
*/
|
||||
int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
|
||||
DRM_STRUCTPROC *p)
|
||||
{
|
||||
struct drm_device *dev = drm_get_device_from_kdev(kdev);
|
||||
int retcode = 0;
|
||||
drm_ioctl_desc_t *ioctl;
|
||||
int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
int nr = DRM_IOCTL_NR(cmd);
|
||||
int is_driver_ioctl = 0;
|
||||
struct drm_file *file_priv;
|
||||
|
||||
retcode = devfs_get_cdevpriv((void **)&file_priv);
|
||||
if (retcode != 0) {
|
||||
DRM_ERROR("can't find authenticator\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
|
||||
++file_priv->ioctl_count;
|
||||
|
||||
DRM_DEBUG("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
|
||||
DRM_CURRENTPID, cmd, nr, (long)dev->device,
|
||||
file_priv->authenticated);
|
||||
|
||||
switch (cmd) {
|
||||
case FIONBIO:
|
||||
case FIOASYNC:
|
||||
return 0;
|
||||
|
||||
case FIOSETOWN:
|
||||
return fsetown(*(int *)data, &dev->buf_sigio);
|
||||
|
||||
case FIOGETOWN:
|
||||
*(int *) data = fgetown(&dev->buf_sigio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IOCGROUP(cmd) != DRM_IOCTL_BASE) {
|
||||
DRM_DEBUG("Bad ioctl group 0x%x\n", (int)IOCGROUP(cmd));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ioctl = &drm_ioctls[nr];
|
||||
/* It's not a core DRM ioctl, try driver-specific. */
|
||||
if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
|
||||
/* The array entries begin at DRM_COMMAND_BASE ioctl nr */
|
||||
nr -= DRM_COMMAND_BASE;
|
||||
if (nr > dev->driver->max_ioctl) {
|
||||
DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n",
|
||||
nr, dev->driver->max_ioctl);
|
||||
return EINVAL;
|
||||
}
|
||||
ioctl = &dev->driver->ioctls[nr];
|
||||
is_driver_ioctl = 1;
|
||||
}
|
||||
func = ioctl->func;
|
||||
|
||||
if (func == NULL) {
|
||||
DRM_DEBUG("no function\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) ||
|
||||
((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
|
||||
((ioctl->flags & DRM_MASTER) && !file_priv->master))
|
||||
return EACCES;
|
||||
|
||||
if (is_driver_ioctl) {
|
||||
DRM_LOCK();
|
||||
/* shared code returns -errno */
|
||||
retcode = -func(dev, data, file_priv);
|
||||
DRM_UNLOCK();
|
||||
} else {
|
||||
retcode = func(dev, data, file_priv);
|
||||
}
|
||||
|
||||
if (retcode != 0)
|
||||
DRM_DEBUG(" returning %d\n", retcode);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
drm_local_map_t *drm_getsarea(struct drm_device *dev)
|
||||
{
|
||||
drm_local_map_t *map;
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
TAILQ_FOREACH(map, &dev->maplist, link) {
|
||||
if (map->type == _DRM_SHM && (map->flags & _DRM_CONTAINS_LOCK))
|
||||
return map;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if DRM_LINUX
|
||||
|
||||
#include <sys/sysproto.h>
|
||||
|
||||
MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
|
||||
|
||||
#define LINUX_IOCTL_DRM_MIN 0x6400
|
||||
#define LINUX_IOCTL_DRM_MAX 0x64ff
|
||||
|
||||
static linux_ioctl_function_t drm_linux_ioctl;
|
||||
static struct linux_ioctl_handler drm_handler = {drm_linux_ioctl,
|
||||
LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
|
||||
|
||||
SYSINIT(drm_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
|
||||
linux_ioctl_register_handler, &drm_handler);
|
||||
SYSUNINIT(drm_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE,
|
||||
linux_ioctl_unregister_handler, &drm_handler);
|
||||
|
||||
/* The bits for in/out are switched on Linux */
|
||||
#define LINUX_IOC_IN IOC_OUT
|
||||
#define LINUX_IOC_OUT IOC_IN
|
||||
|
||||
static int
|
||||
drm_linux_ioctl(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
|
||||
{
|
||||
int error;
|
||||
int cmd = args->cmd;
|
||||
|
||||
args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
|
||||
if (cmd & LINUX_IOC_IN)
|
||||
args->cmd |= IOC_IN;
|
||||
if (cmd & LINUX_IOC_OUT)
|
||||
args->cmd |= IOC_OUT;
|
||||
|
||||
error = ioctl(p, (struct ioctl_args *)args);
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif /* DRM_LINUX */
|
|
@ -1,106 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Daryll Strauss <daryll@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_fops.c
|
||||
* Support code for dealing with the file privates associated with each
|
||||
* open of the DRM device.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/* drm_open_helper is called whenever a process opens /dev/drm. */
|
||||
int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
|
||||
struct drm_device *dev)
|
||||
{
|
||||
struct drm_file *priv;
|
||||
int m = dev2unit(kdev);
|
||||
int retcode;
|
||||
|
||||
if (flags & O_EXCL)
|
||||
return EBUSY; /* No exclusive opens */
|
||||
dev->flags = flags;
|
||||
|
||||
DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m);
|
||||
|
||||
priv = malloc(sizeof(*priv), DRM_MEM_FILES, M_NOWAIT | M_ZERO);
|
||||
if (priv == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
retcode = devfs_set_cdevpriv(priv, drm_close);
|
||||
if (retcode != 0) {
|
||||
free(priv, DRM_MEM_FILES);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
DRM_LOCK();
|
||||
priv->dev = dev;
|
||||
priv->uid = p->td_ucred->cr_svuid;
|
||||
priv->pid = p->td_proc->p_pid;
|
||||
priv->minor = m;
|
||||
priv->ioctl_count = 0;
|
||||
|
||||
/* for compatibility root is always authenticated */
|
||||
priv->authenticated = DRM_SUSER(p);
|
||||
|
||||
if (dev->driver->open) {
|
||||
/* shared code returns -errno */
|
||||
retcode = -dev->driver->open(dev, priv);
|
||||
if (retcode != 0) {
|
||||
devfs_clear_cdevpriv();
|
||||
free(priv, DRM_MEM_FILES);
|
||||
DRM_UNLOCK();
|
||||
return retcode;
|
||||
}
|
||||
}
|
||||
|
||||
/* first opener automatically becomes master */
|
||||
priv->master = TAILQ_EMPTY(&dev->files);
|
||||
|
||||
TAILQ_INSERT_TAIL(&dev->files, priv, link);
|
||||
DRM_UNLOCK();
|
||||
kdev->si_drv1 = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The drm_read and drm_poll are stubs to prevent spurious errors
|
||||
* on older X Servers (4.3.0 and earlier) */
|
||||
|
||||
int drm_read(struct cdev *kdev, struct uio *uio, int ioflag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_poll(struct cdev *kdev, int events, DRM_STRUCTPROC *p)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../shared-core/drm_internal.h
|
|
@ -1,282 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_ioctl.c
|
||||
* Varios minor DRM ioctls not applicable to other files, such as versioning
|
||||
* information and reporting DRM information to userland.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/*
|
||||
* Beginning in revision 1.1 of the DRM interface, getunique will return
|
||||
* a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
|
||||
* before setunique has been called. The format for the bus-specific part of
|
||||
* the unique is not defined for any other bus.
|
||||
*/
|
||||
int drm_getunique(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_unique *u = data;
|
||||
|
||||
if (u->unique_len >= dev->unique_len) {
|
||||
if (DRM_COPY_TO_USER(u->unique, dev->unique, dev->unique_len))
|
||||
return EFAULT;
|
||||
}
|
||||
u->unique_len = dev->unique_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Deprecated in DRM version 1.1, and will return EBUSY when setversion has
|
||||
* requested version 1.1 or greater.
|
||||
*/
|
||||
int drm_setunique(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_unique *u = data;
|
||||
int domain, bus, slot, func, ret;
|
||||
char *busid;
|
||||
|
||||
/* Check and copy in the submitted Bus ID */
|
||||
if (!u->unique_len || u->unique_len > 1024)
|
||||
return EINVAL;
|
||||
|
||||
busid = malloc(u->unique_len + 1, DRM_MEM_DRIVER, M_WAITOK);
|
||||
if (busid == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
if (DRM_COPY_FROM_USER(busid, u->unique, u->unique_len)) {
|
||||
free(busid, DRM_MEM_DRIVER);
|
||||
return EFAULT;
|
||||
}
|
||||
busid[u->unique_len] = '\0';
|
||||
|
||||
/* Return error if the busid submitted doesn't match the device's actual
|
||||
* busid.
|
||||
*/
|
||||
ret = sscanf(busid, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
if (ret != 3) {
|
||||
free(busid, DRM_MEM_DRIVER);
|
||||
return EINVAL;
|
||||
}
|
||||
domain = bus >> 8;
|
||||
bus &= 0xff;
|
||||
|
||||
if ((domain != dev->pci_domain) ||
|
||||
(bus != dev->pci_bus) ||
|
||||
(slot != dev->pci_slot) ||
|
||||
(func != dev->pci_func)) {
|
||||
free(busid, DRM_MEM_DRIVER);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Actually set the device's busid now. */
|
||||
DRM_LOCK();
|
||||
if (dev->unique_len || dev->unique) {
|
||||
DRM_UNLOCK();
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
dev->unique_len = u->unique_len;
|
||||
dev->unique = busid;
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
drm_set_busid(struct drm_device *dev)
|
||||
{
|
||||
|
||||
DRM_LOCK();
|
||||
|
||||
if (dev->unique != NULL) {
|
||||
DRM_UNLOCK();
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
dev->unique_len = 20;
|
||||
dev->unique = malloc(dev->unique_len + 1, DRM_MEM_DRIVER, M_NOWAIT);
|
||||
if (dev->unique == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
|
||||
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_getmap(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_map *map = data;
|
||||
drm_local_map_t *mapinlist;
|
||||
int idx;
|
||||
int i = 0;
|
||||
|
||||
idx = map->offset;
|
||||
|
||||
DRM_LOCK();
|
||||
if (idx < 0) {
|
||||
DRM_UNLOCK();
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
|
||||
if (i == idx) {
|
||||
map->offset = mapinlist->offset;
|
||||
map->size = mapinlist->size;
|
||||
map->type = mapinlist->type;
|
||||
map->flags = mapinlist->flags;
|
||||
map->handle = mapinlist->handle;
|
||||
map->mtrr = mapinlist->mtrr;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
if (mapinlist == NULL)
|
||||
return EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_getclient(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_client *client = data;
|
||||
struct drm_file *pt;
|
||||
int idx;
|
||||
int i = 0;
|
||||
|
||||
idx = client->idx;
|
||||
DRM_LOCK();
|
||||
TAILQ_FOREACH(pt, &dev->files, link) {
|
||||
if (i == idx) {
|
||||
client->auth = pt->authenticated;
|
||||
client->pid = pt->pid;
|
||||
client->uid = pt->uid;
|
||||
client->magic = pt->magic;
|
||||
client->iocs = pt->ioctl_count;
|
||||
DRM_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
int drm_getstats(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_stats *stats = data;
|
||||
int i;
|
||||
|
||||
memset(stats, 0, sizeof(struct drm_stats));
|
||||
|
||||
DRM_LOCK();
|
||||
|
||||
for (i = 0; i < dev->counters; i++) {
|
||||
if (dev->types[i] == _DRM_STAT_LOCK)
|
||||
stats->data[i].value =
|
||||
(dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
|
||||
else
|
||||
stats->data[i].value = atomic_read(&dev->counts[i]);
|
||||
stats->data[i].type = dev->types[i];
|
||||
}
|
||||
|
||||
stats->count = dev->counters;
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DRM_IF_MAJOR 1
|
||||
#define DRM_IF_MINOR 2
|
||||
|
||||
int drm_setversion(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_set_version *sv = data;
|
||||
struct drm_set_version ver;
|
||||
int if_version;
|
||||
|
||||
/* Save the incoming data, and set the response before continuing
|
||||
* any further.
|
||||
*/
|
||||
ver = *sv;
|
||||
sv->drm_di_major = DRM_IF_MAJOR;
|
||||
sv->drm_di_minor = DRM_IF_MINOR;
|
||||
sv->drm_dd_major = dev->driver->major;
|
||||
sv->drm_dd_minor = dev->driver->minor;
|
||||
|
||||
if (ver.drm_di_major != -1) {
|
||||
if (ver.drm_di_major != DRM_IF_MAJOR ||
|
||||
ver.drm_di_minor < 0 || ver.drm_di_minor > DRM_IF_MINOR) {
|
||||
return EINVAL;
|
||||
}
|
||||
if_version = DRM_IF_VERSION(ver.drm_di_major,
|
||||
ver.drm_dd_minor);
|
||||
dev->if_version = DRM_MAX(if_version, dev->if_version);
|
||||
if (ver.drm_di_minor >= 1) {
|
||||
/*
|
||||
* Version 1.1 includes tying of DRM to specific device
|
||||
*/
|
||||
drm_set_busid(dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (ver.drm_dd_major != -1) {
|
||||
if (ver.drm_dd_major != dev->driver->major ||
|
||||
ver.drm_dd_minor < 0 ||
|
||||
ver.drm_dd_minor > dev->driver->minor)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int drm_noop(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
return 0;
|
||||
}
|
|
@ -1,499 +0,0 @@
|
|||
/*-
|
||||
* Copyright 2003 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_irq.c
|
||||
* Support code for handling setup/teardown of interrupt handlers and
|
||||
* handing interrupt handlers off to the drivers.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
||||
int drm_irq_by_busid(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_irq_busid *irq = data;
|
||||
|
||||
if ((irq->busnum >> 8) != dev->pci_domain ||
|
||||
(irq->busnum & 0xff) != dev->pci_bus ||
|
||||
irq->devnum != dev->pci_slot ||
|
||||
irq->funcnum != dev->pci_func)
|
||||
return EINVAL;
|
||||
|
||||
irq->irq = dev->irq;
|
||||
|
||||
DRM_DEBUG("%d:%d:%d => IRQ %d\n",
|
||||
irq->busnum, irq->devnum, irq->funcnum, irq->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
drm_irq_handler_wrap(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = arg;
|
||||
|
||||
DRM_SPINLOCK(&dev->irq_lock);
|
||||
dev->driver->irq_handler(arg);
|
||||
DRM_SPINUNLOCK(&dev->irq_lock);
|
||||
}
|
||||
|
||||
static void vblank_disable_fn(void *arg)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *)arg;
|
||||
int i;
|
||||
|
||||
if (callout_pending(&dev->vblank_disable_timer)) {
|
||||
/* callout was reset */
|
||||
return;
|
||||
}
|
||||
if (!callout_active(&dev->vblank_disable_timer)) {
|
||||
/* callout was stopped */
|
||||
return;
|
||||
}
|
||||
callout_deactivate(&dev->vblank_disable_timer);
|
||||
|
||||
DRM_DEBUG("vblank_disable_allowed=%d\n", dev->vblank_disable_allowed);
|
||||
if (!dev->vblank_disable_allowed)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dev->num_crtcs; i++) {
|
||||
if (atomic_read(&dev->vblank[i].refcount) == 0 &&
|
||||
dev->vblank[i].enabled) {
|
||||
DRM_DEBUG("disabling vblank on crtc %d\n", i);
|
||||
dev->vblank[i].last =
|
||||
dev->driver->get_vblank_counter(dev, i);
|
||||
dev->driver->disable_vblank(dev, i);
|
||||
dev->vblank[i].enabled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drm_vblank_cleanup(struct drm_device *dev)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
/* Bail if the driver didn't call drm_vblank_init() */
|
||||
if (dev->num_crtcs == 0)
|
||||
return;
|
||||
|
||||
DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
|
||||
callout_stop(&dev->vblank_disable_timer);
|
||||
DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
|
||||
|
||||
callout_drain(&dev->vblank_disable_timer);
|
||||
|
||||
vblank_disable_fn((void *)dev);
|
||||
|
||||
free(dev->vblank, DRM_MEM_DRIVER);
|
||||
|
||||
dev->num_crtcs = 0;
|
||||
}
|
||||
|
||||
int drm_vblank_init(struct drm_device *dev, int num_crtcs)
|
||||
{
|
||||
int i, ret = ENOMEM;
|
||||
|
||||
callout_init_mtx(&dev->vblank_disable_timer, &dev->vbl_lock, 0);
|
||||
atomic_set(&dev->vbl_signal_pending, 0);
|
||||
dev->num_crtcs = num_crtcs;
|
||||
|
||||
dev->vblank = malloc(sizeof(struct drm_vblank_info) * num_crtcs,
|
||||
DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
|
||||
if (!dev->vblank)
|
||||
goto err;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* Zero per-crtc vblank stuff */
|
||||
for (i = 0; i < num_crtcs; i++) {
|
||||
DRM_INIT_WAITQUEUE(&dev->vblank[i].queue);
|
||||
TAILQ_INIT(&dev->vblank[i].sigs);
|
||||
atomic_set(&dev->vblank[i].count, 0);
|
||||
atomic_set(&dev->vblank[i].refcount, 0);
|
||||
}
|
||||
|
||||
dev->vblank_disable_allowed = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
drm_vblank_cleanup(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_irq_install(struct drm_device *dev)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
if (dev->irq == 0 || dev->dev_private == NULL)
|
||||
return EINVAL;
|
||||
|
||||
DRM_DEBUG("irq=%d\n", dev->irq);
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->irq_enabled) {
|
||||
DRM_UNLOCK();
|
||||
return EBUSY;
|
||||
}
|
||||
dev->irq_enabled = 1;
|
||||
|
||||
dev->context_flag = 0;
|
||||
|
||||
/* Before installing handler */
|
||||
dev->driver->irq_preinstall(dev);
|
||||
DRM_UNLOCK();
|
||||
|
||||
/* Install handler */
|
||||
#if __FreeBSD_version >= 700031
|
||||
retcode = bus_setup_intr(dev->device, dev->irqr,
|
||||
INTR_TYPE_TTY | INTR_MPSAFE,
|
||||
NULL, drm_irq_handler_wrap, dev, &dev->irqh);
|
||||
#else
|
||||
retcode = bus_setup_intr(dev->device, dev->irqr,
|
||||
INTR_TYPE_TTY | INTR_MPSAFE,
|
||||
drm_irq_handler_wrap, dev, &dev->irqh);
|
||||
#endif
|
||||
if (retcode != 0)
|
||||
goto err;
|
||||
|
||||
/* After installing handler */
|
||||
DRM_LOCK();
|
||||
dev->driver->irq_postinstall(dev);
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
err:
|
||||
DRM_LOCK();
|
||||
dev->irq_enabled = 0;
|
||||
DRM_UNLOCK();
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int drm_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
if (!dev->irq_enabled)
|
||||
return EINVAL;
|
||||
|
||||
dev->irq_enabled = 0;
|
||||
|
||||
DRM_DEBUG("irq=%d\n", dev->irq);
|
||||
|
||||
dev->driver->irq_uninstall(dev);
|
||||
|
||||
DRM_UNLOCK();
|
||||
bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
|
||||
DRM_LOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_control *ctl = data;
|
||||
int err;
|
||||
|
||||
switch (ctl->func) {
|
||||
case DRM_INST_HANDLER:
|
||||
/* Handle drivers whose DRM used to require IRQ setup but the
|
||||
* no longer does.
|
||||
*/
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return 0;
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl->irq != dev->irq)
|
||||
return EINVAL;
|
||||
return drm_irq_install(dev);
|
||||
case DRM_UNINST_HANDLER:
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return 0;
|
||||
DRM_LOCK();
|
||||
err = drm_irq_uninstall(dev);
|
||||
DRM_UNLOCK();
|
||||
return err;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
u32 drm_vblank_count(struct drm_device *dev, int crtc)
|
||||
{
|
||||
return atomic_read(&dev->vblank[crtc].count);
|
||||
}
|
||||
|
||||
static void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||
{
|
||||
u32 cur_vblank, diff;
|
||||
|
||||
/*
|
||||
* Interrupts were disabled prior to this call, so deal with counter
|
||||
* wrap if needed.
|
||||
* NOTE! It's possible we lost a full dev->max_vblank_count events
|
||||
* here if the register is small or we had vblank interrupts off for
|
||||
* a long time.
|
||||
*/
|
||||
cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
|
||||
diff = cur_vblank - dev->vblank[crtc].last;
|
||||
if (cur_vblank < dev->vblank[crtc].last) {
|
||||
diff += dev->max_vblank_count;
|
||||
|
||||
DRM_DEBUG("vblank[%d].last=0x%x, cur_vblank=0x%x => diff=0x%x\n",
|
||||
crtc, dev->vblank[crtc].last, cur_vblank, diff);
|
||||
}
|
||||
|
||||
DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
|
||||
crtc, diff);
|
||||
|
||||
atomic_add(diff, &dev->vblank[crtc].count);
|
||||
}
|
||||
|
||||
int drm_vblank_get(struct drm_device *dev, int crtc)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
int ret = 0;
|
||||
|
||||
DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
|
||||
/* Going from 0->1 means we have to enable interrupts again */
|
||||
atomic_add_acq_int(&dev->vblank[crtc].refcount, 1);
|
||||
DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount);
|
||||
if (dev->vblank[crtc].refcount == 1 &&
|
||||
!dev->vblank[crtc].enabled) {
|
||||
ret = dev->driver->enable_vblank(dev, crtc);
|
||||
if (ret)
|
||||
atomic_dec(&dev->vblank[crtc].refcount);
|
||||
else {
|
||||
dev->vblank[crtc].enabled = 1;
|
||||
drm_update_vblank_count(dev, crtc);
|
||||
}
|
||||
}
|
||||
DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void drm_vblank_put(struct drm_device *dev, int crtc)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
|
||||
/* Last user schedules interrupt disable */
|
||||
atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1);
|
||||
DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount);
|
||||
if (dev->vblank[crtc].refcount == 0)
|
||||
callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ,
|
||||
(timeout_t *)vblank_disable_fn, (void *)dev);
|
||||
DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
|
||||
}
|
||||
|
||||
int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_modeset_ctl *modeset = data;
|
||||
unsigned long irqflags;
|
||||
int crtc, ret = 0;
|
||||
|
||||
DRM_DEBUG("num_crtcs=%d\n", dev->num_crtcs);
|
||||
/* If drm_vblank_init() hasn't been called yet, just no-op */
|
||||
if (!dev->num_crtcs)
|
||||
goto out;
|
||||
|
||||
crtc = modeset->crtc;
|
||||
DRM_DEBUG("crtc=%d\n", crtc);
|
||||
if (crtc >= dev->num_crtcs) {
|
||||
ret = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* To avoid all the problems that might happen if interrupts
|
||||
* were enabled/disabled around or between these calls, we just
|
||||
* have the kernel take a reference on the CRTC (just once though
|
||||
* to avoid corrupting the count if multiple, mismatch calls occur),
|
||||
* so that interrupts remain enabled in the interim.
|
||||
*/
|
||||
switch (modeset->cmd) {
|
||||
case _DRM_PRE_MODESET:
|
||||
DRM_DEBUG("pre-modeset\n");
|
||||
if (!dev->vblank[crtc].inmodeset) {
|
||||
dev->vblank[crtc].inmodeset = 1;
|
||||
drm_vblank_get(dev, crtc);
|
||||
}
|
||||
break;
|
||||
case _DRM_POST_MODESET:
|
||||
DRM_DEBUG("post-modeset\n");
|
||||
if (dev->vblank[crtc].inmodeset) {
|
||||
DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
|
||||
dev->vblank_disable_allowed = 1;
|
||||
dev->vblank[crtc].inmodeset = 0;
|
||||
DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
|
||||
drm_vblank_put(dev, crtc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
union drm_wait_vblank *vblwait = data;
|
||||
unsigned int flags, seq, crtc;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev->irq_enabled)
|
||||
return EINVAL;
|
||||
|
||||
if (vblwait->request.type &
|
||||
~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
|
||||
DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
|
||||
vblwait->request.type,
|
||||
(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
|
||||
crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
|
||||
|
||||
if (crtc >= dev->num_crtcs)
|
||||
return EINVAL;
|
||||
|
||||
ret = drm_vblank_get(dev, crtc);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to acquire vblank counter, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
seq = drm_vblank_count(dev, crtc);
|
||||
|
||||
switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
|
||||
case _DRM_VBLANK_RELATIVE:
|
||||
vblwait->request.sequence += seq;
|
||||
vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
|
||||
case _DRM_VBLANK_ABSOLUTE:
|
||||
break;
|
||||
default:
|
||||
ret = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((flags & _DRM_VBLANK_NEXTONMISS) &&
|
||||
(seq - vblwait->request.sequence) <= (1<<23)) {
|
||||
vblwait->request.sequence = seq + 1;
|
||||
}
|
||||
|
||||
if (flags & _DRM_VBLANK_SIGNAL) {
|
||||
#if 0 /* disabled */
|
||||
drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t),
|
||||
DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
|
||||
if (vbl_sig == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
vbl_sig->sequence = vblwait->request.sequence;
|
||||
vbl_sig->signo = vblwait->request.signal;
|
||||
vbl_sig->pid = DRM_CURRENTPID;
|
||||
|
||||
vblwait->reply.sequence = atomic_read(&dev->vbl_received);
|
||||
|
||||
DRM_SPINLOCK(&dev->vbl_lock);
|
||||
TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
|
||||
DRM_SPINUNLOCK(&dev->vbl_lock);
|
||||
ret = 0;
|
||||
#endif
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
|
||||
vblwait->request.sequence, crtc);
|
||||
for ( ret = 0 ; !ret && !((drm_vblank_count(dev, crtc) -
|
||||
vblwait->request.sequence) <= (1 << 23)) ; ) {
|
||||
mtx_lock(&dev->irq_lock);
|
||||
if (!((drm_vblank_count(dev, crtc) -
|
||||
vblwait->request.sequence) <= (1 << 23)))
|
||||
ret = mtx_sleep(&dev->vblank[crtc].queue,
|
||||
&dev->irq_lock, PCATCH, "vblwtq",
|
||||
3 * DRM_HZ);
|
||||
mtx_unlock(&dev->irq_lock);
|
||||
}
|
||||
|
||||
DRM_DEBUG("return = %d\n", ret);
|
||||
if (ret != EINTR) {
|
||||
struct timeval now;
|
||||
|
||||
microtime(&now);
|
||||
vblwait->reply.tval_sec = now.tv_sec;
|
||||
vblwait->reply.tval_usec = now.tv_usec;
|
||||
vblwait->reply.sequence = drm_vblank_count(dev, crtc);
|
||||
DRM_DEBUG("returning %d to client\n",
|
||||
vblwait->reply.sequence);
|
||||
} else {
|
||||
DRM_DEBUG("vblank wait interrupted by signal\n");
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
drm_vblank_put(dev, crtc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void drm_vbl_send_signals(struct drm_device *dev, int crtc)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0 /* disabled */
|
||||
void drm_vbl_send_signals(struct drm_device *dev, int crtc )
|
||||
{
|
||||
drm_vbl_sig_t *vbl_sig;
|
||||
unsigned int vbl_seq = atomic_read( &dev->vbl_received );
|
||||
struct proc *p;
|
||||
|
||||
vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
|
||||
while (vbl_sig != NULL) {
|
||||
drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
|
||||
|
||||
if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
|
||||
p = pfind(vbl_sig->pid);
|
||||
if (p != NULL)
|
||||
psignal(p, vbl_sig->signo);
|
||||
|
||||
TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link);
|
||||
DRM_FREE(vbl_sig,sizeof(*vbl_sig));
|
||||
}
|
||||
vbl_sig = next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void drm_handle_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
atomic_inc(&dev->vblank[crtc].count);
|
||||
DRM_WAKEUP(&dev->vblank[crtc].queue);
|
||||
drm_vbl_send_signals(dev, crtc);
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/* drm_linux_list.h -- linux list functions for the BSDs.
|
||||
* Created: Mon Apr 7 14:30:16 1999 by anholt@FreeBSD.org
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2003 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
/* Cheat, assume the list_head is at the start of the struct */
|
||||
#define list_entry(entry, type, member) (type *)(entry)
|
||||
|
||||
static __inline__ void
|
||||
INIT_LIST_HEAD(struct list_head *head) {
|
||||
(head)->next = head;
|
||||
(head)->prev = head;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
list_empty(struct list_head *head) {
|
||||
return (head)->next == head;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
list_add_tail(struct list_head *entry, struct list_head *head) {
|
||||
(entry)->prev = (head)->prev;
|
||||
(entry)->next = head;
|
||||
(head)->prev->next = entry;
|
||||
(head)->prev = entry;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
list_del(struct list_head *entry) {
|
||||
(entry)->next->prev = (entry)->prev;
|
||||
(entry)->prev->next = (entry)->next;
|
||||
}
|
||||
|
||||
#define list_for_each(entry, head) \
|
||||
for (entry = (head)->next; entry != head; entry = (entry)->next)
|
||||
|
||||
#define list_for_each_prev(entry, head) \
|
||||
for (entry = (head)->prev; entry != (head); \
|
||||
entry = entry->prev)
|
||||
|
||||
#define list_for_each_safe(entry, temp, head) \
|
||||
for (entry = (head)->next, temp = (entry)->next; \
|
||||
entry != head; \
|
||||
entry = temp, temp = entry->next)
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_lock.c
|
||||
* Implementation of the ioctls and other support code for dealing with the
|
||||
* hardware lock.
|
||||
*
|
||||
* The DRM hardware lock is a shared structure between the kernel and userland.
|
||||
*
|
||||
* On uncontended access where the new context was the last context, the
|
||||
* client may take the lock without dropping down into the kernel, using atomic
|
||||
* compare-and-set.
|
||||
*
|
||||
* If the client finds during compare-and-set that it was not the last owner
|
||||
* of the lock, it calls the DRM lock ioctl, which may sleep waiting for the
|
||||
* lock, and may have side-effects of kernel-managed context switching.
|
||||
*
|
||||
* When the client releases the lock, if the lock is marked as being contended
|
||||
* by another client, then the DRM unlock ioctl is called so that the
|
||||
* contending client may be woken up.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_lock *lock = data;
|
||||
int ret = 0;
|
||||
|
||||
if (lock->context == DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Process %d using kernel context %d\n",
|
||||
DRM_CURRENTPID, lock->context);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
|
||||
lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
|
||||
lock->flags);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) &&
|
||||
lock->context < 0)
|
||||
return EINVAL;
|
||||
|
||||
DRM_LOCK();
|
||||
for (;;) {
|
||||
if (drm_lock_take(&dev->lock, lock->context)) {
|
||||
dev->lock.file_priv = file_priv;
|
||||
dev->lock.lock_time = jiffies;
|
||||
atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
|
||||
break; /* Got lock */
|
||||
}
|
||||
|
||||
/* Contention */
|
||||
ret = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
|
||||
PCATCH, "drmlk2", 0);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
DRM_DEBUG("%d %s\n", lock->context, ret ? "interrupted" : "has lock");
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* XXX: Add signal blocking here */
|
||||
|
||||
if (dev->driver->dma_quiescent != NULL &&
|
||||
(lock->flags & _DRM_LOCK_QUIESCENT))
|
||||
dev->driver->dma_quiescent(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_lock *lock = data;
|
||||
|
||||
DRM_DEBUG("%d (pid %d) requests unlock (0x%08x), flags = 0x%08x\n",
|
||||
lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
|
||||
lock->flags);
|
||||
|
||||
if (lock->context == DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("Process %d using kernel context %d\n",
|
||||
DRM_CURRENTPID, lock->context);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
|
||||
|
||||
DRM_LOCK();
|
||||
drm_lock_transfer(&dev->lock, DRM_KERNEL_CONTEXT);
|
||||
|
||||
if (drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT)) {
|
||||
DRM_ERROR("\n");
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context)
|
||||
{
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned int old, new;
|
||||
|
||||
do {
|
||||
old = *lock;
|
||||
if (old & _DRM_LOCK_HELD)
|
||||
new = old | _DRM_LOCK_CONT;
|
||||
else
|
||||
new = context | _DRM_LOCK_HELD;
|
||||
} while (!atomic_cmpset_int(lock, old, new));
|
||||
|
||||
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
||||
if (old & _DRM_LOCK_HELD) {
|
||||
if (context != DRM_KERNEL_CONTEXT) {
|
||||
DRM_ERROR("%d holds heavyweight lock\n",
|
||||
context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (new == (context | _DRM_LOCK_HELD)) {
|
||||
/* Have lock */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This takes a lock forcibly and hands it to context. Should ONLY be used
|
||||
inside *_unlock to give lock to kernel before calling *_dma_schedule. */
|
||||
int drm_lock_transfer(struct drm_lock_data *lock_data, unsigned int context)
|
||||
{
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned int old, new;
|
||||
|
||||
lock_data->file_priv = NULL;
|
||||
do {
|
||||
old = *lock;
|
||||
new = context | _DRM_LOCK_HELD;
|
||||
} while (!atomic_cmpset_int(lock, old, new));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
|
||||
{
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned int old, new;
|
||||
|
||||
lock_data->file_priv = NULL;
|
||||
do {
|
||||
old = *lock;
|
||||
new = 0;
|
||||
} while (!atomic_cmpset_int(lock, old, new));
|
||||
|
||||
if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
|
||||
DRM_ERROR("%d freed heavyweight lock held by %d\n",
|
||||
context, _DRM_LOCKING_CONTEXT(old));
|
||||
return 1;
|
||||
}
|
||||
DRM_WAKEUP_INT((void *)&lock_data->lock_queue);
|
||||
return 0;
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
/*-
|
||||
*Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_memory.c
|
||||
* Wrappers for kernel memory allocation routines, and MTRR management support.
|
||||
*
|
||||
* This file previously implemented a memory consumption tracking system using
|
||||
* the "area" argument for various different types of allocations, but that
|
||||
* has been stripped out for now.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
MALLOC_DEFINE(DRM_MEM_DMA, "drm_dma", "DRM DMA Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_SAREA, "drm_sarea", "DRM SAREA Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_DRIVER, "drm_driver", "DRM DRIVER Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_MAGIC, "drm_magic", "DRM MAGIC Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_IOCTLS, "drm_ioctls", "DRM IOCTL Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_MAPS, "drm_maps", "DRM MAP Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_BUFS, "drm_bufs", "DRM BUFFER Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_SEGS, "drm_segs", "DRM SEGMENTS Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_PAGES, "drm_pages", "DRM PAGES Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_FILES, "drm_files", "DRM FILE Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_QUEUES, "drm_queues", "DRM QUEUE Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_CMDS, "drm_cmds", "DRM COMMAND Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_MAPPINGS, "drm_mapping", "DRM MAPPING Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_BUFLISTS, "drm_buflists", "DRM BUFLISTS Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_AGPLISTS, "drm_agplists", "DRM AGPLISTS Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_CTXBITMAP, "drm_ctxbitmap",
|
||||
"DRM CTXBITMAP Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_SGLISTS, "drm_sglists", "DRM SGLISTS Data Structures");
|
||||
MALLOC_DEFINE(DRM_MEM_DRAWABLE, "drm_drawable", "DRM DRAWABLE Data Structures");
|
||||
|
||||
void drm_mem_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void drm_mem_uninit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *drm_ioremap_wc(struct drm_device *dev, drm_local_map_t *map)
|
||||
{
|
||||
return pmap_mapdev_attr(map->offset, map->size, PAT_WRITE_COMBINING);
|
||||
}
|
||||
|
||||
void *drm_ioremap(struct drm_device *dev, drm_local_map_t *map)
|
||||
{
|
||||
return pmap_mapdev(map->offset, map->size);
|
||||
}
|
||||
|
||||
void drm_ioremapfree(drm_local_map_t *map)
|
||||
{
|
||||
pmap_unmapdev((vm_offset_t) map->handle, map->size);
|
||||
}
|
||||
|
||||
int
|
||||
drm_mtrr_add(unsigned long offset, size_t size, int flags)
|
||||
{
|
||||
int act;
|
||||
struct mem_range_desc mrdesc;
|
||||
|
||||
mrdesc.mr_base = offset;
|
||||
mrdesc.mr_len = size;
|
||||
mrdesc.mr_flags = flags;
|
||||
act = MEMRANGE_SET_UPDATE;
|
||||
strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
|
||||
return mem_range_attr_set(&mrdesc, &act);
|
||||
}
|
||||
|
||||
int
|
||||
drm_mtrr_del(int __unused handle, unsigned long offset, size_t size, int flags)
|
||||
{
|
||||
int act;
|
||||
struct mem_range_desc mrdesc;
|
||||
|
||||
mrdesc.mr_base = offset;
|
||||
mrdesc.mr_len = size;
|
||||
mrdesc.mr_flags = flags;
|
||||
act = MEMRANGE_SET_REMOVE;
|
||||
strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
|
||||
return mem_range_attr_set(&mrdesc, &act);
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../shared-core/drm_mode.h
|
|
@ -1,125 +0,0 @@
|
|||
/*-
|
||||
* Copyright 2003 Eric Anholt.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file drm_pci.h
|
||||
* \brief PCI consistent, DMA-accessible memory allocation.
|
||||
*
|
||||
* \author Eric Anholt <anholt@FreeBSD.org>
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
/**********************************************************************/
|
||||
/** \name PCI memory */
|
||||
/*@{*/
|
||||
|
||||
static void
|
||||
drm_pci_busdma_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
{
|
||||
drm_dma_handle_t *dmah = arg;
|
||||
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
KASSERT(nsegs == 1, ("drm_pci_busdma_callback: bad dma segment count"));
|
||||
dmah->busaddr = segs[0].ds_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocate a physically contiguous DMA-accessible consistent
|
||||
* memory block.
|
||||
*/
|
||||
drm_dma_handle_t *
|
||||
drm_pci_alloc(struct drm_device *dev, size_t size,
|
||||
size_t align, dma_addr_t maxaddr)
|
||||
{
|
||||
drm_dma_handle_t *dmah;
|
||||
int ret;
|
||||
|
||||
/* Need power-of-two alignment, so fail the allocation if it isn't. */
|
||||
if ((align & (align - 1)) != 0) {
|
||||
DRM_ERROR("drm_pci_alloc with non-power-of-two alignment %d\n",
|
||||
(int)align);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dmah = malloc(sizeof(drm_dma_handle_t), DRM_MEM_DMA, M_ZERO | M_NOWAIT);
|
||||
if (dmah == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Make sure we aren't holding locks here */
|
||||
mtx_assert(&dev->dev_lock, MA_NOTOWNED);
|
||||
if (mtx_owned(&dev->dev_lock))
|
||||
DRM_ERROR("called while holding dev_lock\n");
|
||||
mtx_assert(&dev->dma_lock, MA_NOTOWNED);
|
||||
if (mtx_owned(&dev->dma_lock))
|
||||
DRM_ERROR("called while holding dma_lock\n");
|
||||
|
||||
ret = bus_dma_tag_create(NULL, align, 0, /* tag, align, boundary */
|
||||
maxaddr, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
|
||||
NULL, NULL, /* filtfunc, filtfuncargs */
|
||||
size, 1, size, /* maxsize, nsegs, maxsegsize */
|
||||
0, NULL, NULL, /* flags, lockfunc, lockfuncargs */
|
||||
&dmah->tag);
|
||||
if (ret != 0) {
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr,
|
||||
BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmah->map);
|
||||
if (ret != 0) {
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr, size,
|
||||
drm_pci_busdma_callback, dmah, BUS_DMA_NOWAIT | BUS_DMA_NOCACHE);
|
||||
if (ret != 0) {
|
||||
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dmah;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Free a DMA-accessible consistent memory block.
|
||||
*/
|
||||
void
|
||||
drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah)
|
||||
{
|
||||
if (dmah == NULL)
|
||||
return;
|
||||
|
||||
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
}
|
||||
|
||||
/*@}*/
|
|
@ -1 +0,0 @@
|
|||
../shared-core/drm_sarea.h
|
|
@ -1,190 +0,0 @@
|
|||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
* Eric Anholt <anholt@FreeBSD.org>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file drm_scatter.c
|
||||
* Allocation of memory for scatter-gather mappings by the graphics chip.
|
||||
*
|
||||
* The memory allocated here is then made into an aperture in the card
|
||||
* by drm_ati_pcigart_init().
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
static void drm_sg_alloc_cb(void *arg, bus_dma_segment_t *segs,
|
||||
int nsegs, int error);
|
||||
|
||||
int
|
||||
drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather *request)
|
||||
{
|
||||
struct drm_sg_mem *entry;
|
||||
struct drm_dma_handle *dmah;
|
||||
unsigned long pages;
|
||||
int ret;
|
||||
|
||||
if (dev->sg)
|
||||
return EINVAL;
|
||||
|
||||
entry = malloc(sizeof(*entry), DRM_MEM_SGLISTS, M_WAITOK | M_ZERO);
|
||||
if (!entry)
|
||||
return ENOMEM;
|
||||
|
||||
pages = round_page(request->size) / PAGE_SIZE;
|
||||
DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages);
|
||||
|
||||
entry->pages = pages;
|
||||
|
||||
entry->busaddr = malloc(pages * sizeof(*entry->busaddr), DRM_MEM_PAGES,
|
||||
M_WAITOK | M_ZERO);
|
||||
if (!entry->busaddr) {
|
||||
free(entry, DRM_MEM_SGLISTS);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
dmah = malloc(sizeof(struct drm_dma_handle), DRM_MEM_DMA,
|
||||
M_ZERO | M_NOWAIT);
|
||||
if (dmah == NULL) {
|
||||
free(entry->busaddr, DRM_MEM_PAGES);
|
||||
free(entry, DRM_MEM_SGLISTS);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
ret = bus_dma_tag_create(NULL, PAGE_SIZE, 0, /* tag, align, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
|
||||
NULL, NULL, /* filtfunc, filtfuncargs */
|
||||
request->size, pages, /* maxsize, nsegs */
|
||||
PAGE_SIZE, 0, /* maxsegsize, flags */
|
||||
NULL, NULL, /* lockfunc, lockfuncargs */
|
||||
&dmah->tag);
|
||||
if (ret != 0) {
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
free(entry->busaddr, DRM_MEM_PAGES);
|
||||
free(entry, DRM_MEM_SGLISTS);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr,
|
||||
BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmah->map);
|
||||
if (ret != 0) {
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
free(entry->busaddr, DRM_MEM_PAGES);
|
||||
free(entry, DRM_MEM_SGLISTS);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
|
||||
request->size, drm_sg_alloc_cb, entry,
|
||||
BUS_DMA_NOWAIT | BUS_DMA_NOCACHE);
|
||||
if (ret != 0) {
|
||||
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
free(entry->busaddr, DRM_MEM_PAGES);
|
||||
free(entry, DRM_MEM_SGLISTS);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
entry->sg_dmah = dmah;
|
||||
entry->handle = (unsigned long)dmah->vaddr;
|
||||
|
||||
DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
|
||||
|
||||
entry->virtual = (void *)entry->handle;
|
||||
request->handle = entry->handle;
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->sg) {
|
||||
DRM_UNLOCK();
|
||||
drm_sg_cleanup(entry);
|
||||
return EINVAL;
|
||||
}
|
||||
dev->sg = entry;
|
||||
DRM_UNLOCK();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
drm_sg_alloc_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
{
|
||||
struct drm_sg_mem *entry = arg;
|
||||
int i;
|
||||
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
for(i = 0 ; i < nsegs ; i++) {
|
||||
entry->busaddr[i] = segs[i].ds_addr;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_scatter_gather *request = data;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
return drm_sg_alloc(dev, request);
|
||||
}
|
||||
|
||||
void
|
||||
drm_sg_cleanup(struct drm_sg_mem *entry)
|
||||
{
|
||||
struct drm_dma_handle *dmah = entry->sg_dmah;
|
||||
|
||||
bus_dmamap_unload(dmah->tag, dmah->map);
|
||||
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||
bus_dma_tag_destroy(dmah->tag);
|
||||
free(dmah, DRM_MEM_DMA);
|
||||
free(entry->busaddr, DRM_MEM_PAGES);
|
||||
free(entry, DRM_MEM_SGLISTS);
|
||||
}
|
||||
|
||||
int
|
||||
drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_scatter_gather *request = data;
|
||||
struct drm_sg_mem *entry;
|
||||
|
||||
DRM_LOCK();
|
||||
entry = dev->sg;
|
||||
dev->sg = NULL;
|
||||
DRM_UNLOCK();
|
||||
|
||||
if (!entry || entry->handle != request->handle)
|
||||
return EINVAL;
|
||||
|
||||
DRM_DEBUG("sg free virtual = 0x%lx\n", entry->handle);
|
||||
|
||||
drm_sg_cleanup(entry);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,312 +0,0 @@
|
|||
/*-
|
||||
* Copyright 2003 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file drm_sysctl.c
|
||||
* Implementation of various sysctls for controlling DRM behavior and reporting
|
||||
* debug information.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
static int drm_name_info DRM_SYSCTL_HANDLER_ARGS;
|
||||
static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS;
|
||||
static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS;
|
||||
static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS;
|
||||
|
||||
struct drm_sysctl_list {
|
||||
const char *name;
|
||||
int (*f) DRM_SYSCTL_HANDLER_ARGS;
|
||||
} drm_sysctl_list[] = {
|
||||
{"name", drm_name_info},
|
||||
{"vm", drm_vm_info},
|
||||
{"clients", drm_clients_info},
|
||||
{"bufs", drm_bufs_info},
|
||||
};
|
||||
#define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0]))
|
||||
|
||||
struct drm_sysctl_info {
|
||||
struct sysctl_ctx_list ctx;
|
||||
char name[2];
|
||||
};
|
||||
|
||||
int drm_sysctl_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_sysctl_info *info;
|
||||
struct sysctl_oid *oid;
|
||||
struct sysctl_oid *top, *drioid;
|
||||
int i;
|
||||
|
||||
info = malloc(sizeof *info, DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
|
||||
if ( !info )
|
||||
return 1;
|
||||
dev->sysctl = info;
|
||||
|
||||
/* Add the sysctl node for DRI if it doesn't already exist */
|
||||
drioid = SYSCTL_ADD_NODE( &info->ctx, &sysctl__hw_children, OID_AUTO, "dri", CTLFLAG_RW, NULL, "DRI Graphics");
|
||||
if (!drioid)
|
||||
return 1;
|
||||
|
||||
/* Find the next free slot under hw.dri */
|
||||
i = 0;
|
||||
SLIST_FOREACH(oid, SYSCTL_CHILDREN(drioid), oid_link) {
|
||||
if (i <= oid->oid_arg2)
|
||||
i = oid->oid_arg2 + 1;
|
||||
}
|
||||
if (i>9)
|
||||
return 1;
|
||||
|
||||
/* Add the hw.dri.x for our device */
|
||||
info->name[0] = '0' + i;
|
||||
info->name[1] = 0;
|
||||
top = SYSCTL_ADD_NODE( &info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
|
||||
if (!top)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
|
||||
oid = SYSCTL_ADD_OID(&info->ctx,
|
||||
SYSCTL_CHILDREN(top),
|
||||
OID_AUTO,
|
||||
drm_sysctl_list[i].name,
|
||||
CTLTYPE_INT | CTLFLAG_RD,
|
||||
dev,
|
||||
0,
|
||||
drm_sysctl_list[i].f,
|
||||
"A",
|
||||
NULL);
|
||||
if (!oid)
|
||||
return 1;
|
||||
}
|
||||
SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(top), OID_AUTO, "debug",
|
||||
CTLFLAG_RW, &drm_debug_flag, sizeof(drm_debug_flag),
|
||||
"Enable debugging output");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_sysctl_cleanup(struct drm_device *dev)
|
||||
{
|
||||
int error;
|
||||
error = sysctl_ctx_free( &dev->sysctl->ctx );
|
||||
|
||||
free(dev->sysctl, DRM_MEM_DRIVER);
|
||||
dev->sysctl = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#define DRM_SYSCTL_PRINT(fmt, arg...) \
|
||||
do { \
|
||||
snprintf(buf, sizeof(buf), fmt, ##arg); \
|
||||
retcode = SYSCTL_OUT(req, buf, strlen(buf)); \
|
||||
if (retcode) \
|
||||
goto done; \
|
||||
} while (0)
|
||||
|
||||
static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
struct drm_device *dev = arg1;
|
||||
char buf[128];
|
||||
int retcode;
|
||||
int hasunique = 0;
|
||||
|
||||
DRM_SYSCTL_PRINT("%s 0x%x", dev->driver->name, dev2udev(dev->devnode));
|
||||
|
||||
DRM_LOCK();
|
||||
if (dev->unique) {
|
||||
snprintf(buf, sizeof(buf), " %s", dev->unique);
|
||||
hasunique = 1;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
if (hasunique)
|
||||
SYSCTL_OUT(req, buf, strlen(buf));
|
||||
|
||||
SYSCTL_OUT(req, "", 1);
|
||||
|
||||
done:
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
struct drm_device *dev = arg1;
|
||||
drm_local_map_t *map, *tempmaps;
|
||||
const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
|
||||
const char *type, *yesno;
|
||||
int i, mapcount;
|
||||
char buf[128];
|
||||
int retcode;
|
||||
|
||||
/* We can't hold the lock while doing SYSCTL_OUTs, so allocate a
|
||||
* temporary copy of all the map entries and then SYSCTL_OUT that.
|
||||
*/
|
||||
DRM_LOCK();
|
||||
|
||||
mapcount = 0;
|
||||
TAILQ_FOREACH(map, &dev->maplist, link)
|
||||
mapcount++;
|
||||
|
||||
tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, DRM_MEM_DRIVER,
|
||||
M_NOWAIT);
|
||||
if (tempmaps == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH(map, &dev->maplist, link)
|
||||
tempmaps[i++] = *map;
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_SYSCTL_PRINT("\nslot offset size "
|
||||
"type flags address mtrr\n");
|
||||
|
||||
for (i = 0; i < mapcount; i++) {
|
||||
map = &tempmaps[i];
|
||||
|
||||
if (map->type < 0 || map->type > 4)
|
||||
type = "??";
|
||||
else
|
||||
type = types[map->type];
|
||||
|
||||
if (!map->mtrr)
|
||||
yesno = "no";
|
||||
else
|
||||
yesno = "yes";
|
||||
|
||||
DRM_SYSCTL_PRINT(
|
||||
"%4d 0x%016lx 0x%08lx %4.4s 0x%02x 0x%016lx %s\n", i,
|
||||
map->offset, map->size, type, map->flags,
|
||||
(unsigned long)map->handle, yesno);
|
||||
}
|
||||
SYSCTL_OUT(req, "", 1);
|
||||
|
||||
done:
|
||||
free(tempmaps, DRM_MEM_DRIVER);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
struct drm_device *dev = arg1;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
drm_device_dma_t tempdma;
|
||||
int *templists;
|
||||
int i;
|
||||
char buf[128];
|
||||
int retcode;
|
||||
|
||||
/* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
|
||||
* copy of the whole structure and the relevant data from buflist.
|
||||
*/
|
||||
DRM_LOCK();
|
||||
if (dma == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
DRM_SPINLOCK(&dev->dma_lock);
|
||||
tempdma = *dma;
|
||||
templists = malloc(sizeof(int) * dma->buf_count, DRM_MEM_DRIVER,
|
||||
M_NOWAIT);
|
||||
for (i = 0; i < dma->buf_count; i++)
|
||||
templists[i] = dma->buflist[i]->list;
|
||||
dma = &tempdma;
|
||||
DRM_SPINUNLOCK(&dev->dma_lock);
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n");
|
||||
for (i = 0; i <= DRM_MAX_ORDER; i++) {
|
||||
if (dma->bufs[i].buf_count)
|
||||
DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
|
||||
i,
|
||||
dma->bufs[i].buf_size,
|
||||
dma->bufs[i].buf_count,
|
||||
atomic_read(&dma->bufs[i]
|
||||
.freelist.count),
|
||||
dma->bufs[i].seg_count,
|
||||
dma->bufs[i].seg_count
|
||||
*(1 << dma->bufs[i].page_order),
|
||||
(dma->bufs[i].seg_count
|
||||
* (1 << dma->bufs[i].page_order))
|
||||
* PAGE_SIZE / 1024);
|
||||
}
|
||||
DRM_SYSCTL_PRINT("\n");
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (i && !(i%32)) DRM_SYSCTL_PRINT("\n");
|
||||
DRM_SYSCTL_PRINT(" %d", templists[i]);
|
||||
}
|
||||
DRM_SYSCTL_PRINT("\n");
|
||||
|
||||
SYSCTL_OUT(req, "", 1);
|
||||
done:
|
||||
free(templists, DRM_MEM_DRIVER);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
|
||||
{
|
||||
struct drm_device *dev = arg1;
|
||||
struct drm_file *priv, *tempprivs;
|
||||
char buf[128];
|
||||
int retcode;
|
||||
int privcount, i;
|
||||
|
||||
DRM_LOCK();
|
||||
|
||||
privcount = 0;
|
||||
TAILQ_FOREACH(priv, &dev->files, link)
|
||||
privcount++;
|
||||
|
||||
tempprivs = malloc(sizeof(struct drm_file) * privcount, DRM_MEM_DRIVER,
|
||||
M_NOWAIT);
|
||||
if (tempprivs == NULL) {
|
||||
DRM_UNLOCK();
|
||||
return ENOMEM;
|
||||
}
|
||||
i = 0;
|
||||
TAILQ_FOREACH(priv, &dev->files, link)
|
||||
tempprivs[i++] = *priv;
|
||||
|
||||
DRM_UNLOCK();
|
||||
|
||||
DRM_SYSCTL_PRINT("\na dev pid uid magic ioctls\n");
|
||||
for (i = 0; i < privcount; i++) {
|
||||
priv = &tempprivs[i];
|
||||
DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n",
|
||||
priv->authenticated ? 'y' : 'n',
|
||||
priv->minor,
|
||||
priv->pid,
|
||||
priv->uid,
|
||||
priv->magic,
|
||||
priv->ioctl_count);
|
||||
}
|
||||
|
||||
SYSCTL_OUT(req, "", 1);
|
||||
done:
|
||||
free(tempprivs, DRM_MEM_DRIVER);
|
||||
return retcode;
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
/*-
|
||||
* Copyright 2003 Eric Anholt
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file drm_vm.c
|
||||
* Support code for mmaping of DRM maps.
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
||||
int drm_mmap(struct cdev *kdev, vm_offset_t offset, vm_paddr_t *paddr,
|
||||
int prot)
|
||||
{
|
||||
struct drm_device *dev = drm_get_device_from_kdev(kdev);
|
||||
struct drm_file *file_priv = NULL;
|
||||
drm_local_map_t *map;
|
||||
enum drm_map_type type;
|
||||
vm_paddr_t phys;
|
||||
int error;
|
||||
|
||||
/* d_mmap gets called twice, we can only reference file_priv during
|
||||
* the first call. We need to assume that if error is EBADF the
|
||||
* call was succesful and the client is authenticated.
|
||||
*/
|
||||
error = devfs_get_cdevpriv((void **)&file_priv);
|
||||
if (error == ENOENT) {
|
||||
DRM_ERROR("Could not find authenticator!\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (file_priv && !file_priv->authenticated)
|
||||
return EACCES;
|
||||
|
||||
if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) {
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
|
||||
DRM_SPINLOCK(&dev->dma_lock);
|
||||
|
||||
if (dma->pagelist != NULL) {
|
||||
unsigned long page = offset >> PAGE_SHIFT;
|
||||
unsigned long phys = dma->pagelist[page];
|
||||
|
||||
DRM_SPINUNLOCK(&dev->dma_lock);
|
||||
*paddr = phys;
|
||||
return 0;
|
||||
} else {
|
||||
DRM_SPINUNLOCK(&dev->dma_lock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* A sequential search of a linked list is
|
||||
fine here because: 1) there will only be
|
||||
about 5-10 entries in the list and, 2) a
|
||||
DRI client only has to do this mapping
|
||||
once, so it doesn't have to be optimized
|
||||
for performance, even if the list was a
|
||||
bit longer. */
|
||||
DRM_LOCK();
|
||||
TAILQ_FOREACH(map, &dev->maplist, link) {
|
||||
if (offset >= map->offset && offset < map->offset + map->size)
|
||||
break;
|
||||
}
|
||||
|
||||
if (map == NULL) {
|
||||
DRM_DEBUG("Can't find map, requested offset = %016lx\n",
|
||||
offset);
|
||||
TAILQ_FOREACH(map, &dev->maplist, link) {
|
||||
DRM_DEBUG("map offset = %016lx, handle = %016lx\n",
|
||||
map->offset, (unsigned long)map->handle);
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
return -1;
|
||||
}
|
||||
if (((map->flags&_DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) {
|
||||
DRM_UNLOCK();
|
||||
DRM_DEBUG("restricted map\n");
|
||||
return -1;
|
||||
}
|
||||
type = map->type;
|
||||
DRM_UNLOCK();
|
||||
|
||||
switch (type) {
|
||||
case _DRM_FRAME_BUFFER:
|
||||
case _DRM_REGISTERS:
|
||||
case _DRM_AGP:
|
||||
phys = offset;
|
||||
break;
|
||||
case _DRM_CONSISTENT:
|
||||
phys = vtophys((char *)map->handle + (offset - map->offset));
|
||||
break;
|
||||
case _DRM_SCATTER_GATHER:
|
||||
case _DRM_SHM:
|
||||
phys = vtophys(offset);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("bad map type %d\n", type);
|
||||
return -1; /* This should never happen. */
|
||||
}
|
||||
|
||||
*paddr = phys;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
KMOD = i915
|
||||
NO_MAN = YES
|
||||
SRCS = i915_dma.c i915_drv.c i915_irq.c i915_mem.c i915_suspend.c
|
||||
SRCS += device_if.h bus_if.h pci_if.h opt_drm.h
|
||||
CFLAGS += ${DEBUG_FLAGS} -I. -I..
|
||||
|
||||
.if defined(DRM_DEBUG)
|
||||
DRM_DEBUG_OPT= "\#define DRM_DEBUG 1"
|
||||
.endif
|
||||
|
||||
.if !defined(DRM_NOLINUX)
|
||||
DRM_LINUX_OPT= "\#define DRM_LINUX 1"
|
||||
.endif
|
||||
|
||||
opt_drm.h:
|
||||
touch opt_drm.h
|
||||
echo $(DRM_DEBUG_OPT) >> opt_drm.h
|
||||
echo $(DRM_LINUX_OPT) >> opt_drm.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
|
@ -1 +0,0 @@
|
|||
../shared-core/i915_dma.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/i915_drm.h
|
|
@ -1,158 +0,0 @@
|
|||
/* i915_drv.c -- Intel i915 driver -*- linux-c -*-
|
||||
* Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t i915_pciidlist[] = {
|
||||
i915_PCI_IDS
|
||||
};
|
||||
|
||||
static int i915_suspend(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!dev || !dev_priv) {
|
||||
DRM_ERROR("dev: 0x%lx, dev_priv: 0x%lx\n",
|
||||
(unsigned long) dev, (unsigned long) dev_priv);
|
||||
DRM_ERROR("DRM not initialized, aborting suspend.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
i915_save_state(dev);
|
||||
|
||||
return (bus_generic_suspend(kdev));
|
||||
}
|
||||
|
||||
static int i915_resume(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
|
||||
i915_restore_state(dev);
|
||||
|
||||
return (bus_generic_resume(kdev));
|
||||
}
|
||||
|
||||
static void i915_configure(struct drm_device *dev)
|
||||
{
|
||||
dev->driver->driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
|
||||
DRIVER_HAVE_IRQ;
|
||||
|
||||
dev->driver->buf_priv_size = sizeof(drm_i915_private_t);
|
||||
dev->driver->load = i915_driver_load;
|
||||
dev->driver->unload = i915_driver_unload;
|
||||
dev->driver->preclose = i915_driver_preclose;
|
||||
dev->driver->lastclose = i915_driver_lastclose;
|
||||
dev->driver->device_is_agp = i915_driver_device_is_agp;
|
||||
dev->driver->enable_vblank = i915_enable_vblank;
|
||||
dev->driver->disable_vblank = i915_disable_vblank;
|
||||
dev->driver->irq_preinstall = i915_driver_irq_preinstall;
|
||||
dev->driver->irq_postinstall = i915_driver_irq_postinstall;
|
||||
dev->driver->irq_uninstall = i915_driver_irq_uninstall;
|
||||
dev->driver->irq_handler = i915_driver_irq_handler;
|
||||
|
||||
dev->driver->ioctls = i915_ioctls;
|
||||
dev->driver->max_ioctl = i915_max_ioctl;
|
||||
|
||||
dev->driver->name = DRIVER_NAME;
|
||||
dev->driver->desc = DRIVER_DESC;
|
||||
dev->driver->date = DRIVER_DATE;
|
||||
dev->driver->major = DRIVER_MAJOR;
|
||||
dev->driver->minor = DRIVER_MINOR;
|
||||
dev->driver->patchlevel = DRIVER_PATCHLEVEL;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_probe(device_t kdev)
|
||||
{
|
||||
return drm_probe(kdev, i915_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
i915_attach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
|
||||
dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
i915_configure(dev);
|
||||
|
||||
return drm_attach(kdev, i915_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
i915_detach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
int ret;
|
||||
|
||||
ret = drm_detach(kdev);
|
||||
|
||||
free(dev->driver, DRM_MEM_DRIVER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static device_method_t i915_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, i915_probe),
|
||||
DEVMETHOD(device_attach, i915_attach),
|
||||
DEVMETHOD(device_suspend, i915_suspend),
|
||||
DEVMETHOD(device_resume, i915_resume),
|
||||
DEVMETHOD(device_detach, i915_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t i915_driver = {
|
||||
#if __FreeBSD_version >= 700010
|
||||
"drm",
|
||||
#else
|
||||
"drmsub",
|
||||
#endif
|
||||
i915_methods,
|
||||
sizeof(struct drm_device)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(i915, vgapci, i915_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(i915, agp, i915_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(i915, drm, 1, 1, 1);
|
|
@ -1 +0,0 @@
|
|||
../shared-core/i915_drv.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/i915_irq.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/i915_mem.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/i915_reg.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/i915_suspend.c
|
|
@ -1,23 +0,0 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
KMOD = mach64
|
||||
NO_MAN = YES
|
||||
SRCS = mach64_dma.c mach64_drv.c mach64_irq.c mach64_state.c
|
||||
SRCS += device_if.h bus_if.h pci_if.h opt_drm.h
|
||||
CFLAGS += ${DEBUG_FLAGS} -I. -I..
|
||||
|
||||
.if defined(DRM_DEBUG)
|
||||
DRM_DEBUG_OPT= "\#define DRM_DEBUG 1"
|
||||
.endif
|
||||
|
||||
.if !defined(DRM_NOLINUX)
|
||||
DRM_LINUX_OPT= "\#define DRM_LINUX 1"
|
||||
.endif
|
||||
|
||||
opt_drm.h:
|
||||
touch opt_drm.h
|
||||
echo $(DRM_DEBUG_OPT) >> opt_drm.h
|
||||
echo $(DRM_LINUX_OPT) >> opt_drm.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mach64_dma.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mach64_drm.h
|
|
@ -1,135 +0,0 @@
|
|||
/* mach64_drv.c -- ATI Rage 128 driver -*- linux-c -*-
|
||||
* Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mach64_drm.h"
|
||||
#include "mach64_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t mach64_pciidlist[] = {
|
||||
mach64_PCI_IDS
|
||||
};
|
||||
|
||||
static void mach64_configure(struct drm_device *dev)
|
||||
{
|
||||
dev->driver->driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
|
||||
|
||||
dev->driver->buf_priv_size = 1; /* No dev_priv */
|
||||
dev->driver->load = mach64_driver_load;
|
||||
dev->driver->lastclose = mach64_driver_lastclose;
|
||||
dev->driver->get_vblank_counter = mach64_get_vblank_counter;
|
||||
dev->driver->enable_vblank = mach64_enable_vblank;
|
||||
dev->driver->disable_vblank = mach64_disable_vblank;
|
||||
dev->driver->irq_preinstall = mach64_driver_irq_preinstall;
|
||||
dev->driver->irq_postinstall = mach64_driver_irq_postinstall;
|
||||
dev->driver->irq_uninstall = mach64_driver_irq_uninstall;
|
||||
dev->driver->irq_handler = mach64_driver_irq_handler;
|
||||
dev->driver->dma_ioctl = mach64_dma_buffers;
|
||||
|
||||
dev->driver->ioctls = mach64_ioctls;
|
||||
dev->driver->max_ioctl = mach64_max_ioctl;
|
||||
|
||||
dev->driver->name = DRIVER_NAME;
|
||||
dev->driver->desc = DRIVER_DESC;
|
||||
dev->driver->date = DRIVER_DATE;
|
||||
dev->driver->major = DRIVER_MAJOR;
|
||||
dev->driver->minor = DRIVER_MINOR;
|
||||
dev->driver->patchlevel = DRIVER_PATCHLEVEL;
|
||||
}
|
||||
|
||||
static int
|
||||
mach64_probe(device_t kdev)
|
||||
{
|
||||
return drm_probe(kdev, mach64_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
mach64_attach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
|
||||
dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
mach64_configure(dev);
|
||||
|
||||
return drm_attach(kdev, mach64_pciidlist);
|
||||
}
|
||||
|
||||
int
|
||||
mach64_driver_load(struct drm_device * dev, unsigned long flags)
|
||||
{
|
||||
return drm_vblank_init(dev, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
mach64_detach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
int ret;
|
||||
|
||||
ret = drm_detach(kdev);
|
||||
|
||||
free(dev->driver, DRM_MEM_DRIVER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static device_method_t mach64_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, mach64_probe),
|
||||
DEVMETHOD(device_attach, mach64_attach),
|
||||
DEVMETHOD(device_detach, mach64_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t mach64_driver = {
|
||||
"drm",
|
||||
mach64_methods,
|
||||
sizeof(struct drm_device)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(mach64, vgapci, mach64_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(mach64, pci, mach64_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(mach64, drm, 1, 1, 1);
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mach64_drv.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mach64_irq.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mach64_state.c
|
|
@ -1,23 +0,0 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
KMOD= mga
|
||||
NO_MAN= YES
|
||||
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
|
||||
CFLAGS+= ${DEBUG_FLAGS} -I. -I..
|
||||
|
||||
.if defined(DRM_DEBUG)
|
||||
DRM_DEBUG_OPT= "\#define DRM_DEBUG 1"
|
||||
.endif
|
||||
|
||||
.if !defined(DRM_NOLINUX)
|
||||
DRM_LINUX_OPT= "\#define DRM_LINUX 1"
|
||||
.endif
|
||||
|
||||
opt_drm.h:
|
||||
touch opt_drm.h
|
||||
echo $(DRM_DEBUG_OPT) >> opt_drm.h
|
||||
echo $(DRM_LINUX_OPT) >> opt_drm.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mga_dma.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mga_drm.h
|
|
@ -1,172 +0,0 @@
|
|||
/* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*-
|
||||
* Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mga_drm.h"
|
||||
#include "mga_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t mga_pciidlist[] = {
|
||||
mga_PCI_IDS
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if the device really is AGP or not.
|
||||
*
|
||||
* In addition to the usual tests performed by \c drm_device_is_agp, this
|
||||
* function detects PCI G450 cards that appear to the system exactly like
|
||||
* AGP G450 cards.
|
||||
*
|
||||
* \param dev The device to be tested.
|
||||
*
|
||||
* \returns
|
||||
* If the device is a PCI G450, zero is returned. Otherwise non-zero is
|
||||
* returned.
|
||||
*
|
||||
* \bug
|
||||
* This function needs to be filled in! The implementation in
|
||||
* linux-core/mga_drv.c shows what needs to be done.
|
||||
*/
|
||||
static int mga_driver_device_is_agp(struct drm_device * dev)
|
||||
{
|
||||
device_t bus;
|
||||
|
||||
/* There are PCI versions of the G450. These cards have the
|
||||
* same PCI ID as the AGP G450, but have an additional PCI-to-PCI
|
||||
* bridge chip. We detect these cards, which are not currently
|
||||
* supported by this driver, by looking at the device ID of the
|
||||
* bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the
|
||||
* device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
|
||||
* device.
|
||||
*/
|
||||
#if __FreeBSD_version >= 700010
|
||||
bus = device_get_parent(device_get_parent(dev->device));
|
||||
#else
|
||||
bus = device_get_parent(dev->device);
|
||||
#endif
|
||||
if (pci_get_device(dev->device) == 0x0525 &&
|
||||
pci_get_vendor(bus) == 0x3388 &&
|
||||
pci_get_device(bus) == 0x0021)
|
||||
return DRM_IS_NOT_AGP;
|
||||
else
|
||||
return DRM_MIGHT_BE_AGP;
|
||||
}
|
||||
|
||||
static void mga_configure(struct drm_device *dev)
|
||||
{
|
||||
dev->driver->driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
|
||||
|
||||
dev->driver->buf_priv_size = sizeof(drm_mga_buf_priv_t);
|
||||
dev->driver->load = mga_driver_load;
|
||||
dev->driver->unload = mga_driver_unload;
|
||||
dev->driver->lastclose = mga_driver_lastclose;
|
||||
dev->driver->get_vblank_counter = mga_get_vblank_counter;
|
||||
dev->driver->enable_vblank = mga_enable_vblank;
|
||||
dev->driver->disable_vblank = mga_disable_vblank;
|
||||
dev->driver->irq_preinstall = mga_driver_irq_preinstall;
|
||||
dev->driver->irq_postinstall = mga_driver_irq_postinstall;
|
||||
dev->driver->irq_uninstall = mga_driver_irq_uninstall;
|
||||
dev->driver->irq_handler = mga_driver_irq_handler;
|
||||
dev->driver->dma_ioctl = mga_dma_buffers;
|
||||
dev->driver->dma_quiescent = mga_driver_dma_quiescent;
|
||||
dev->driver->device_is_agp = mga_driver_device_is_agp;
|
||||
|
||||
dev->driver->ioctls = mga_ioctls;
|
||||
dev->driver->max_ioctl = mga_max_ioctl;
|
||||
|
||||
dev->driver->name = DRIVER_NAME;
|
||||
dev->driver->desc = DRIVER_DESC;
|
||||
dev->driver->date = DRIVER_DATE;
|
||||
dev->driver->major = DRIVER_MAJOR;
|
||||
dev->driver->minor = DRIVER_MINOR;
|
||||
dev->driver->patchlevel = DRIVER_PATCHLEVEL;
|
||||
}
|
||||
|
||||
static int
|
||||
mga_probe(device_t kdev)
|
||||
{
|
||||
return drm_probe(kdev, mga_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
mga_attach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
|
||||
dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
mga_configure(dev);
|
||||
|
||||
return drm_attach(kdev, mga_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
mga_detach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
int ret;
|
||||
|
||||
ret = drm_detach(kdev);
|
||||
|
||||
free(dev->driver, DRM_MEM_DRIVER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static device_method_t mga_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, mga_probe),
|
||||
DEVMETHOD(device_attach, mga_attach),
|
||||
DEVMETHOD(device_detach, mga_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t mga_driver = {
|
||||
"drm",
|
||||
mga_methods,
|
||||
sizeof(struct drm_device)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(mga, vgapci, mga_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(mga, pci, mga_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(mga, drm, 1, 1, 1);
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mga_drv.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mga_irq.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mga_state.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mga_ucode.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/mga_warp.c
|
|
@ -1 +0,0 @@
|
|||
/usr/src/sys
|
|
@ -1,33 +0,0 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
KMOD = nouveau
|
||||
NO_MAN = YES
|
||||
SRCS = nouveau_drv.c nouveau_state.c nouveau_mem.c nouveau_object.c \
|
||||
nouveau_sgdma.c nouveau_fifo.c nouveau_notifier.c nouveau_dma.c \
|
||||
nouveau_irq.c nouveau_swmthd.c \
|
||||
nv04_timer.c \
|
||||
nv04_mc.c nv40_mc.c nv50_mc.c \
|
||||
nv04_fb.c nv10_fb.c nv40_fb.c \
|
||||
nv04_fifo.c nv10_fifo.c nv40_fifo.c nv50_fifo.c \
|
||||
nv04_graph.c nv10_graph.c nv20_graph.c \
|
||||
nv40_graph.c nv50_graph.c \
|
||||
nv04_instmem.c nv50_instmem.c
|
||||
# nouveau_bo.c nouveau_fence.c \
|
||||
SRCS += device_if.h bus_if.h pci_if.h opt_drm.h
|
||||
CFLAGS += ${DEBUG_FLAGS} -I. -I..
|
||||
|
||||
.if defined(DRM_DEBUG)
|
||||
DRM_DEBUG_OPT= "\#define DRM_DEBUG 1"
|
||||
.endif
|
||||
|
||||
.if !defined(DRM_NOLINUX)
|
||||
DRM_LINUX_OPT= "\#define DRM_LINUX 1"
|
||||
.endif
|
||||
|
||||
opt_drm.h:
|
||||
touch opt_drm.h
|
||||
echo $(DRM_DEBUG_OPT) >> opt_drm.h
|
||||
echo $(DRM_LINUX_OPT) >> opt_drm.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
|
@ -1 +0,0 @@
|
|||
/usr/src/sys/amd64/include
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_dma.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_dma.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_drm.h
|
|
@ -1,148 +0,0 @@
|
|||
/* nouveau_drv.c.c -- nouveau nouveau driver -*- linux-c -*-
|
||||
* Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
extern struct drm_ioctl_desc nouveau_ioctls[];
|
||||
extern int nouveau_max_ioctl;
|
||||
|
||||
/* drv_PCI_IDs for nouveau is just to match the vendor id */
|
||||
static struct drm_pci_id_list nouveau_pciidlist[] = {
|
||||
{0x10DE, 0, 0, "NVidia Display Adapter"}, \
|
||||
{0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
static void nouveau_configure(struct drm_device *dev)
|
||||
{
|
||||
dev->driver->driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ;
|
||||
|
||||
dev->driver->buf_priv_size = sizeof(struct drm_nouveau_private);
|
||||
dev->driver->load = nouveau_load;
|
||||
dev->driver->unload = nouveau_unload;
|
||||
dev->driver->firstopen = nouveau_firstopen;
|
||||
dev->driver->preclose = nouveau_preclose;
|
||||
dev->driver->lastclose = nouveau_lastclose;
|
||||
dev->driver->irq_preinstall = nouveau_irq_preinstall;
|
||||
dev->driver->irq_postinstall = nouveau_irq_postinstall;
|
||||
dev->driver->irq_uninstall = nouveau_irq_uninstall;
|
||||
dev->driver->irq_handler = nouveau_irq_handler;
|
||||
|
||||
dev->driver->ioctls = nouveau_ioctls;
|
||||
dev->driver->max_ioctl = nouveau_max_ioctl;
|
||||
|
||||
dev->driver->name = DRIVER_NAME;
|
||||
dev->driver->desc = DRIVER_DESC;
|
||||
dev->driver->date = DRIVER_DATE;
|
||||
dev->driver->major = DRIVER_MAJOR;
|
||||
dev->driver->minor = DRIVER_MINOR;
|
||||
dev->driver->patchlevel = DRIVER_PATCHLEVEL;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_probe(device_t kdev)
|
||||
{
|
||||
int vendor;
|
||||
|
||||
if (pci_get_class(kdev) == PCIC_DISPLAY) {
|
||||
vendor = pci_get_vendor(kdev);
|
||||
if (vendor == 0x10de) {
|
||||
|
||||
const char *ident;
|
||||
char model[64];
|
||||
|
||||
if (pci_get_vpd_ident(kdev, &ident) == 0) {
|
||||
snprintf(model, 64, "%s", ident);
|
||||
device_set_desc_copy(kdev, model);
|
||||
DRM_DEBUG("VPD : %s\n", model);
|
||||
}
|
||||
|
||||
return drm_probe(kdev, nouveau_pciidlist);
|
||||
}
|
||||
}
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_attach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
|
||||
dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
nouveau_configure(dev);
|
||||
|
||||
return drm_attach(kdev, nouveau_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_detach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
int ret;
|
||||
|
||||
ret = drm_detach(kdev);
|
||||
|
||||
free(dev->driver, DRM_MEM_DRIVER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static device_method_t nouveau_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, nouveau_probe),
|
||||
DEVMETHOD(device_attach, nouveau_attach),
|
||||
DEVMETHOD(device_detach, nouveau_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t nouveau_driver = {
|
||||
#if __FreeBSD_version >= 700010
|
||||
"drm",
|
||||
#else
|
||||
"drmsub",
|
||||
#endif
|
||||
nouveau_methods,
|
||||
sizeof(struct drm_device)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(nouveau, vgapci, nouveau_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(nouveau, agp, nouveau_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(nouveau, drm, 1, 1, 1);
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_drv.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_fifo.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_irq.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_mem.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_notifier.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_object.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_reg.h
|
|
@ -1,357 +0,0 @@
|
|||
#include "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
|
||||
#define NV_CTXDMA_PAGE_SHIFT 12
|
||||
#define NV_CTXDMA_PAGE_SIZE (1 << NV_CTXDMA_PAGE_SHIFT)
|
||||
#define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1)
|
||||
|
||||
#if 0
|
||||
struct nouveau_sgdma_be {
|
||||
struct drm_ttm_backend backend;
|
||||
struct drm_device *dev;
|
||||
|
||||
int pages;
|
||||
int pages_populated;
|
||||
dma_addr_t *pagelist;
|
||||
int is_bound;
|
||||
|
||||
unsigned int pte_start;
|
||||
};
|
||||
|
||||
static int
|
||||
nouveau_sgdma_needs_ub_cache_adjust(struct drm_ttm_backend *be)
|
||||
{
|
||||
return ((be->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages,
|
||||
struct page **pages, struct page *dummy_read_page)
|
||||
{
|
||||
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
|
||||
int p, d, o;
|
||||
|
||||
DRM_DEBUG("num_pages = %ld\n", num_pages);
|
||||
|
||||
if (nvbe->pagelist)
|
||||
return -EINVAL;
|
||||
nvbe->pages = (num_pages << PAGE_SHIFT) >> NV_CTXDMA_PAGE_SHIFT;
|
||||
nvbe->pagelist = drm_alloc(nvbe->pages*sizeof(dma_addr_t),
|
||||
DRM_MEM_PAGES);
|
||||
|
||||
nvbe->pages_populated = d = 0;
|
||||
for (p = 0; p < num_pages; p++) {
|
||||
for (o = 0; o < PAGE_SIZE; o += NV_CTXDMA_PAGE_SIZE) {
|
||||
struct page *page = pages[p];
|
||||
if (!page)
|
||||
page = dummy_read_page;
|
||||
#ifdef __linux__
|
||||
nvbe->pagelist[d] = pci_map_page(nvbe->dev->pdev,
|
||||
page, o,
|
||||
NV_CTXDMA_PAGE_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
|
||||
if (pci_dma_mapping_error(nvbe->dev->pdev, nvbe->pagelist[d])) {
|
||||
#else
|
||||
if (pci_dma_mapping_error(nvbe->pagelist[d])) {
|
||||
#endif
|
||||
be->func->clear(be);
|
||||
DRM_ERROR("pci_map_page failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
nvbe->pages_populated = ++d;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_sgdma_clear(struct drm_ttm_backend *be)
|
||||
{
|
||||
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
|
||||
#ifdef __linux__
|
||||
int d;
|
||||
#endif
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (nvbe && nvbe->pagelist) {
|
||||
if (nvbe->is_bound)
|
||||
be->func->unbind(be);
|
||||
#ifdef __linux__
|
||||
for (d = 0; d < nvbe->pages_populated; d++) {
|
||||
pci_unmap_page(nvbe->dev->pdev, nvbe->pagelist[d],
|
||||
NV_CTXDMA_PAGE_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
}
|
||||
#endif
|
||||
drm_free(nvbe->pagelist, nvbe->pages*sizeof(dma_addr_t),
|
||||
DRM_MEM_PAGES);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_sgdma_bind(struct drm_ttm_backend *be, struct drm_bo_mem_reg *mem)
|
||||
{
|
||||
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
|
||||
struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
|
||||
struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
|
||||
uint64_t offset = (mem->mm_node->start << PAGE_SHIFT);
|
||||
uint32_t i;
|
||||
|
||||
DRM_DEBUG("pg=0x%lx (0x%llx), cached=%d\n", mem->mm_node->start,
|
||||
(unsigned long long)offset,
|
||||
(mem->flags & DRM_BO_FLAG_CACHED) == 1);
|
||||
|
||||
if (offset & NV_CTXDMA_PAGE_MASK)
|
||||
return -EINVAL;
|
||||
nvbe->pte_start = (offset >> NV_CTXDMA_PAGE_SHIFT);
|
||||
if (dev_priv->card_type < NV_50)
|
||||
nvbe->pte_start += 2; /* skip ctxdma header */
|
||||
|
||||
for (i = nvbe->pte_start; i < nvbe->pte_start + nvbe->pages; i++) {
|
||||
uint64_t pteval = nvbe->pagelist[i - nvbe->pte_start];
|
||||
|
||||
if (pteval & NV_CTXDMA_PAGE_MASK) {
|
||||
DRM_ERROR("Bad pteval 0x%llx\n",
|
||||
(unsigned long long)pteval);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
INSTANCE_WR(gpuobj, i, pteval | 3);
|
||||
} else {
|
||||
INSTANCE_WR(gpuobj, (i<<1)+0, pteval | 0x21);
|
||||
INSTANCE_WR(gpuobj, (i<<1)+1, 0x00000000);
|
||||
}
|
||||
}
|
||||
|
||||
nvbe->is_bound = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_sgdma_unbind(struct drm_ttm_backend *be)
|
||||
{
|
||||
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
|
||||
struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (nvbe->is_bound) {
|
||||
struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
|
||||
unsigned int pte;
|
||||
|
||||
pte = nvbe->pte_start;
|
||||
while (pte < (nvbe->pte_start + nvbe->pages)) {
|
||||
uint64_t pteval = dev_priv->gart_info.sg_dummy_bus;
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
INSTANCE_WR(gpuobj, pte, pteval | 3);
|
||||
} else {
|
||||
INSTANCE_WR(gpuobj, (pte<<1)+0, pteval | 0x21);
|
||||
INSTANCE_WR(gpuobj, (pte<<1)+1, 0x00000000);
|
||||
}
|
||||
|
||||
pte++;
|
||||
}
|
||||
|
||||
nvbe->is_bound = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_sgdma_destroy(struct drm_ttm_backend *be)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
if (be) {
|
||||
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
|
||||
if (nvbe) {
|
||||
if (nvbe->pagelist)
|
||||
be->func->clear(be);
|
||||
drm_ctl_free(nvbe, sizeof(*nvbe), DRM_MEM_TTM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct drm_ttm_backend_func nouveau_sgdma_backend = {
|
||||
.needs_ub_cache_adjust = nouveau_sgdma_needs_ub_cache_adjust,
|
||||
.populate = nouveau_sgdma_populate,
|
||||
.clear = nouveau_sgdma_clear,
|
||||
.bind = nouveau_sgdma_bind,
|
||||
.unbind = nouveau_sgdma_unbind,
|
||||
.destroy = nouveau_sgdma_destroy
|
||||
};
|
||||
|
||||
struct drm_ttm_backend *
|
||||
nouveau_sgdma_init_ttm(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_sgdma_be *nvbe;
|
||||
|
||||
if (!dev_priv->gart_info.sg_ctxdma)
|
||||
return NULL;
|
||||
|
||||
nvbe = drm_ctl_calloc(1, sizeof(*nvbe), DRM_MEM_TTM);
|
||||
if (!nvbe)
|
||||
return NULL;
|
||||
|
||||
nvbe->dev = dev;
|
||||
|
||||
nvbe->backend.func = &nouveau_sgdma_backend;
|
||||
|
||||
return &nvbe->backend;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
nouveau_sgdma_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *gpuobj = NULL;
|
||||
uint32_t aper_size, obj_size;
|
||||
int i, ret;
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
aper_size = (64 * 1024 * 1024);
|
||||
obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
|
||||
obj_size += 8; /* ctxdma header */
|
||||
} else {
|
||||
/* 1 entire VM page table */
|
||||
aper_size = (512 * 1024 * 1024);
|
||||
obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
|
||||
NVOBJ_FLAG_ALLOW_NO_REFS |
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE, &gpuobj))) {
|
||||
DRM_ERROR("Error creating sgdma object: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#ifdef __linux__
|
||||
dev_priv->gart_info.sg_dummy_page =
|
||||
alloc_page(GFP_KERNEL|__GFP_DMA32);
|
||||
set_page_locked(dev_priv->gart_info.sg_dummy_page);
|
||||
dev_priv->gart_info.sg_dummy_bus =
|
||||
pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
#endif
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
|
||||
* confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE
|
||||
* on those cards? */
|
||||
INSTANCE_WR(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY |
|
||||
(1 << 12) /* PT present */ |
|
||||
(0 << 13) /* PT *not* linear */ |
|
||||
(NV_DMA_ACCESS_RW << 14) |
|
||||
(NV_DMA_TARGET_PCI << 16));
|
||||
INSTANCE_WR(gpuobj, 1, aper_size - 1);
|
||||
for (i=2; i<2+(aper_size>>12); i++) {
|
||||
INSTANCE_WR(gpuobj, i,
|
||||
dev_priv->gart_info.sg_dummy_bus | 3);
|
||||
}
|
||||
} else {
|
||||
for (i=0; i<obj_size; i+=8) {
|
||||
INSTANCE_WR(gpuobj, (i+0)/4,
|
||||
dev_priv->gart_info.sg_dummy_bus | 0x21);
|
||||
INSTANCE_WR(gpuobj, (i+4)/4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
dev_priv->gart_info.type = NOUVEAU_GART_SGDMA;
|
||||
dev_priv->gart_info.aper_base = 0;
|
||||
dev_priv->gart_info.aper_size = aper_size;
|
||||
dev_priv->gart_info.sg_ctxdma = gpuobj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_sgdma_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->gart_info.sg_dummy_page) {
|
||||
#ifdef __linux__
|
||||
pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus,
|
||||
NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
unlock_page(dev_priv->gart_info.sg_dummy_page);
|
||||
__free_page(dev_priv->gart_info.sg_dummy_page);
|
||||
#endif
|
||||
dev_priv->gart_info.sg_dummy_page = NULL;
|
||||
dev_priv->gart_info.sg_dummy_bus = 0;
|
||||
}
|
||||
|
||||
nouveau_gpuobj_del(dev, &dev_priv->gart_info.sg_ctxdma);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
nouveau_sgdma_nottm_hack_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_ttm_backend *be;
|
||||
struct drm_scatter_gather sgreq;
|
||||
struct drm_mm_node mm_node;
|
||||
struct drm_bo_mem_reg mem;
|
||||
int ret;
|
||||
|
||||
dev_priv->gart_info.sg_be = nouveau_sgdma_init_ttm(dev);
|
||||
if (!dev_priv->gart_info.sg_be)
|
||||
return -ENOMEM;
|
||||
be = dev_priv->gart_info.sg_be;
|
||||
|
||||
/* Hack the aperture size down to the amount of system memory
|
||||
* we're going to bind into it.
|
||||
*/
|
||||
if (dev_priv->gart_info.aper_size > 32*1024*1024)
|
||||
dev_priv->gart_info.aper_size = 32*1024*1024;
|
||||
|
||||
sgreq.size = dev_priv->gart_info.aper_size;
|
||||
if ((ret = drm_sg_alloc(dev, &sgreq))) {
|
||||
DRM_ERROR("drm_sg_alloc failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
dev_priv->gart_info.sg_handle = sgreq.handle;
|
||||
|
||||
if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist, dev->bm.dummy_read_page))) {
|
||||
DRM_ERROR("failed populate: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mm_node.start = 0;
|
||||
mem.mm_node = &mm_node;
|
||||
|
||||
if ((ret = be->func->bind(be, &mem))) {
|
||||
DRM_ERROR("failed bind: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_sgdma_nottm_hack_takedown(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
|
||||
int pte;
|
||||
|
||||
pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
*page = INSTANCE_RD(gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_ERROR("Unimplemented on NV50\n");
|
||||
return -EINVAL;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_state.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_swmthd.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nouveau_swmthd.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv04_fb.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv04_fifo.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv04_graph.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv04_instmem.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv04_mc.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv04_timer.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv10_fb.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv10_fifo.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv10_graph.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv20_graph.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv40_fb.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv40_fifo.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv40_graph.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv40_mc.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv50_fifo.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv50_graph.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv50_grctx.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv50_instmem.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/nv50_mc.c
|
|
@ -1,23 +0,0 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
KMOD = r128
|
||||
NO_MAN = YES
|
||||
SRCS = r128_cce.c r128_drv.c r128_state.c r128_irq.c
|
||||
SRCS += device_if.h bus_if.h pci_if.h opt_drm.h
|
||||
CFLAGS += ${DEBUG_FLAGS} -I. -I..
|
||||
|
||||
.if defined(DRM_DEBUG)
|
||||
DRM_DEBUG_OPT= "\#define DRM_DEBUG 1"
|
||||
.endif
|
||||
|
||||
.if !defined(DRM_NOLINUX)
|
||||
DRM_LINUX_OPT= "\#define DRM_LINUX 1"
|
||||
.endif
|
||||
|
||||
opt_drm.h:
|
||||
touch opt_drm.h
|
||||
echo $(DRM_DEBUG_OPT) >> opt_drm.h
|
||||
echo $(DRM_LINUX_OPT) >> opt_drm.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
|
@ -1 +0,0 @@
|
|||
../shared-core/r128_cce.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/r128_drm.h
|
|
@ -1,133 +0,0 @@
|
|||
/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
|
||||
* Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
|
||||
*/
|
||||
/*-
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "r128_drm.h"
|
||||
#include "r128_drv.h"
|
||||
#include "drm_pciids.h"
|
||||
|
||||
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
|
||||
static drm_pci_id_list_t r128_pciidlist[] = {
|
||||
r128_PCI_IDS
|
||||
};
|
||||
|
||||
static void r128_configure(struct drm_device *dev)
|
||||
{
|
||||
dev->driver->driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
|
||||
DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
|
||||
|
||||
dev->driver->buf_priv_size = sizeof(drm_r128_buf_priv_t);
|
||||
dev->driver->load = r128_driver_load;
|
||||
dev->driver->preclose = r128_driver_preclose;
|
||||
dev->driver->lastclose = r128_driver_lastclose;
|
||||
dev->driver->get_vblank_counter = r128_get_vblank_counter;
|
||||
dev->driver->enable_vblank = r128_enable_vblank;
|
||||
dev->driver->disable_vblank = r128_disable_vblank;
|
||||
dev->driver->irq_preinstall = r128_driver_irq_preinstall;
|
||||
dev->driver->irq_postinstall = r128_driver_irq_postinstall;
|
||||
dev->driver->irq_uninstall = r128_driver_irq_uninstall;
|
||||
dev->driver->irq_handler = r128_driver_irq_handler;
|
||||
dev->driver->dma_ioctl = r128_cce_buffers;
|
||||
|
||||
dev->driver->ioctls = r128_ioctls;
|
||||
dev->driver->max_ioctl = r128_max_ioctl;
|
||||
|
||||
dev->driver->name = DRIVER_NAME;
|
||||
dev->driver->desc = DRIVER_DESC;
|
||||
dev->driver->date = DRIVER_DATE;
|
||||
dev->driver->major = DRIVER_MAJOR;
|
||||
dev->driver->minor = DRIVER_MINOR;
|
||||
dev->driver->patchlevel = DRIVER_PATCHLEVEL;
|
||||
}
|
||||
|
||||
static int
|
||||
r128_probe(device_t kdev)
|
||||
{
|
||||
return drm_probe(kdev, r128_pciidlist);
|
||||
}
|
||||
|
||||
static int
|
||||
r128_attach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
|
||||
dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
r128_configure(dev);
|
||||
|
||||
return drm_attach(kdev, r128_pciidlist);
|
||||
}
|
||||
|
||||
int r128_driver_load(struct drm_device * dev, unsigned long flags)
|
||||
{
|
||||
return drm_vblank_init(dev, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
r128_detach(device_t kdev)
|
||||
{
|
||||
struct drm_device *dev = device_get_softc(kdev);
|
||||
int ret;
|
||||
|
||||
ret = drm_detach(kdev);
|
||||
|
||||
free(dev->driver, DRM_MEM_DRIVER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static device_method_t r128_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, r128_probe),
|
||||
DEVMETHOD(device_attach, r128_attach),
|
||||
DEVMETHOD(device_detach, r128_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t r128_driver = {
|
||||
"drm",
|
||||
r128_methods,
|
||||
sizeof(struct drm_device)
|
||||
};
|
||||
|
||||
extern devclass_t drm_devclass;
|
||||
#if __FreeBSD_version >= 700010
|
||||
DRIVER_MODULE(r128, vgapci, r128_driver, drm_devclass, 0, 0);
|
||||
#else
|
||||
DRIVER_MODULE(r128, pci, r128_driver, drm_devclass, 0, 0);
|
||||
#endif
|
||||
MODULE_DEPEND(r128, drm, 1, 1, 1);
|
|
@ -1 +0,0 @@
|
|||
../shared-core/r128_drv.h
|
|
@ -1 +0,0 @@
|
|||
../shared-core/r128_irq.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/r128_state.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/r300_cmdbuf.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/r300_reg.h
|
|
@ -1,28 +0,0 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
KMOD = radeon
|
||||
NO_MAN = YES
|
||||
SRCS = r300_cmdbuf.c radeon_cp.c radeon_drv.c radeon_state.c radeon_irq.c \
|
||||
radeon_mem.c
|
||||
SRCS += device_if.h bus_if.h pci_if.h opt_drm.h
|
||||
CFLAGS += ${DEBUG_FLAGS} -I. -I..
|
||||
|
||||
.if ${CC} != "icc"
|
||||
CFLAGS += --param large-function-growth=1000
|
||||
.endif
|
||||
|
||||
.if defined(DRM_DEBUG)
|
||||
DRM_DEBUG_OPT= "\#define DRM_DEBUG 1"
|
||||
.endif
|
||||
|
||||
.if !defined(DRM_NOLINUX)
|
||||
DRM_LINUX_OPT= "\#define DRM_LINUX 1"
|
||||
.endif
|
||||
|
||||
opt_drm.h:
|
||||
touch opt_drm.h
|
||||
echo $(DRM_DEBUG_OPT) >> opt_drm.h
|
||||
echo $(DRM_LINUX_OPT) >> opt_drm.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
|
@ -1 +0,0 @@
|
|||
../shared-core/radeon_cp.c
|
|
@ -1 +0,0 @@
|
|||
../shared-core/radeon_drm.h
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue