drm_dma.c revision 152909
15191Swollman/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
25191Swollman * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
35191Swollman */
45191Swollman/*-
55191Swollman * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
65191Swollman * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
75191Swollman * All Rights Reserved.
85191Swollman *
95191Swollman * Permission is hereby granted, free of charge, to any person obtaining a
105191Swollman * copy of this software and associated documentation files (the "Software"),
115191Swollman * to deal in the Software without restriction, including without limitation
125191Swollman * the rights to use, copy, modify, merge, publish, distribute, sublicense,
135191Swollman * and/or sell copies of the Software, and to permit persons to whom the
145191Swollman * Software is furnished to do so, subject to the following conditions:
155191Swollman *
165191Swollman * The above copyright notice and this permission notice (including the next
175191Swollman * paragraph) shall be included in all copies or substantial portions of the
185191Swollman * Software.
195191Swollman *
205191Swollman * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
215191Swollman * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
225191Swollman * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
235191Swollman * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
245191Swollman * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
255191Swollman * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
265191Swollman * OTHER DEALINGS IN THE SOFTWARE.
275191Swollman *
285191Swollman * Authors:
295191Swollman *    Rickard E. (Rik) Faith <faith@valinux.com>
305191Swollman *    Gareth Hughes <gareth@valinux.com>
315191Swollman *
325191Swollman */
335191Swollman
3450477Speter#include <sys/cdefs.h>
355191Swollman__FBSDID("$FreeBSD: head/sys/dev/drm/drm_dma.c 152909 2005-11-28 23:13:57Z anholt $");
365191Swollman
375191Swollman#include "dev/drm/drmP.h"
385191Swollman
395191Swollmanint drm_dma_setup(drm_device_t *dev)
405191Swollman{
415191Swollman
425191Swollman	dev->dma = malloc(sizeof(*dev->dma), M_DRM, M_NOWAIT | M_ZERO);
435191Swollman	if (dev->dma == NULL)
445191Swollman		return DRM_ERR(ENOMEM);
455191Swollman
465191Swollman	DRM_SPININIT(dev->dma_lock, "drmdma");
4724204Sbde
485191Swollman	return 0;
495191Swollman}
505191Swollman
515191Swollmanvoid drm_dma_takedown(drm_device_t *dev)
525191Swollman{
535191Swollman	drm_device_dma_t  *dma = dev->dma;
5432350Seivind	int		  i, j;
5554263Sshin
565191Swollman	if (dma == NULL)
575191Swollman		return;
585191Swollman
595191Swollman				/* Clear dma buffers */
605191Swollman	for (i = 0; i <= DRM_MAX_ORDER; i++) {
615191Swollman		if (dma->bufs[i].seg_count) {
625191Swollman			DRM_DEBUG("order %d: buf_count = %d,"
6312569Sbde				  " seg_count = %d\n",
6410429Sbde				  i,
6510429Sbde				  dma->bufs[i].buf_count,
6641757Seivind				  dma->bufs[i].seg_count);
6741757Seivind			for (j = 0; j < dma->bufs[i].seg_count; j++) {
685191Swollman				drm_pci_free(dev, dma->bufs[i].seglist[j]);
6941757Seivind			}
7041757Seivind			free(dma->bufs[i].seglist, M_DRM);
715191Swollman		}
725191Swollman
735191Swollman	   	if (dma->bufs[i].buf_count) {
7412569Sbde		   	for (j = 0; j < dma->bufs[i].buf_count; j++) {
7512569Sbde				free(dma->bufs[i].buflist[j].dev_private,
765191Swollman				    M_DRM);
7741757Seivind			}
785191Swollman		   	free(dma->bufs[i].buflist, M_DRM);
795191Swollman		}
805191Swollman	}
815191Swollman
8241757Seivind	free(dma->buflist, M_DRM);
8341757Seivind	free(dma->pagelist, M_DRM);
845191Swollman	free(dev->dma, M_DRM);
855191Swollman	dev->dma = NULL;
865191Swollman	DRM_SPINUNINIT(dev->dma_lock);
8753115Sphk}
885191Swollman
8913937Swollman
905191Swollmanvoid drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
915191Swollman{
925191Swollman	if (!buf) return;
9341757Seivind
945191Swollman	buf->pending  = 0;
955191Swollman	buf->filp     = NULL;
965191Swollman	buf->used     = 0;
975191Swollman}
985191Swollman
995191Swollmanvoid drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
10041757Seivind{
10110957Swollman	drm_device_dma_t *dma = dev->dma;
10210957Swollman	int		 i;
10310957Swollman
10410957Swollman	if (!dma) return;
10510957Swollman	for (i = 0; i < dma->buf_count; i++) {
10610957Swollman		if (dma->buflist[i]->filp == filp) {
10710957Swollman			switch (dma->buflist[i]->list) {
10810957Swollman			case DRM_LIST_NONE:
10941757Seivind				drm_free_buffer(dev, dma->buflist[i]);
1105191Swollman				break;
1115191Swollman			case DRM_LIST_WAIT:
1125191Swollman				dma->buflist[i]->list = DRM_LIST_RECLAIM;
1135191Swollman				break;
1145191Swollman			default:
1155191Swollman				/* Buffer already on hardware. */
1165191Swollman				break;
1175191Swollman			}
1185191Swollman		}
1195191Swollman	}
1205191Swollman}
1215191Swollman
1225191Swollman/* Call into the driver-specific DMA handler */
1238876Srgrimesint drm_dma(DRM_IOCTL_ARGS)
12441757Seivind{
1255191Swollman	DRM_DEVICE;
1265191Swollman
1275191Swollman	if (dev->driver.dma_ioctl) {
1285191Swollman		return dev->driver.dma_ioctl(kdev, cmd, data, flags, p, filp);
1295191Swollman	} else {
1305191Swollman		DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
1315191Swollman		return EINVAL;
1325191Swollman	}
1335191Swollman}
1345191Swollman