1282199Sdumbbell/**
2282199Sdumbbell * \file drm_dma.c
3282199Sdumbbell * DMA IOCTL and function support
4282199Sdumbbell *
5282199Sdumbbell * \author Rickard E. (Rik) Faith <faith@valinux.com>
6282199Sdumbbell * \author Gareth Hughes <gareth@valinux.com>
7282199Sdumbbell */
8282199Sdumbbell
9235783Skib/*-
10282199Sdumbbell * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
11282199Sdumbbell *
12235783Skib * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
13235783Skib * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14235783Skib * All Rights Reserved.
15235783Skib *
16235783Skib * Permission is hereby granted, free of charge, to any person obtaining a
17235783Skib * copy of this software and associated documentation files (the "Software"),
18235783Skib * to deal in the Software without restriction, including without limitation
19235783Skib * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20235783Skib * and/or sell copies of the Software, and to permit persons to whom the
21235783Skib * Software is furnished to do so, subject to the following conditions:
22235783Skib *
23235783Skib * The above copyright notice and this permission notice (including the next
24235783Skib * paragraph) shall be included in all copies or substantial portions of the
25235783Skib * Software.
26235783Skib *
27235783Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28235783Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29235783Skib * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
30235783Skib * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31235783Skib * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32235783Skib * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33235783Skib * OTHER DEALINGS IN THE SOFTWARE.
34235783Skib */
35235783Skib
36235783Skib#include <sys/cdefs.h>
37235783Skib__FBSDID("$FreeBSD$");
38235783Skib
39282199Sdumbbell#include <dev/drm2/drmP.h>
40282199Sdumbbell
41282199Sdumbbell/**
42282199Sdumbbell * Initialize the DMA data.
43235783Skib *
44282199Sdumbbell * \param dev DRM device.
45282199Sdumbbell * \return zero on success or a negative value on failure.
46282199Sdumbbell *
47282199Sdumbbell * Allocate and initialize a drm_device_dma structure.
48235783Skib */
49235783Skibint drm_dma_setup(struct drm_device *dev)
50235783Skib{
51282199Sdumbbell	int i;
52235783Skib
53235783Skib	dev->dma = malloc(sizeof(*dev->dma), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
54282199Sdumbbell	if (!dev->dma)
55282199Sdumbbell		return -ENOMEM;
56235783Skib
57282199Sdumbbell	for (i = 0; i <= DRM_MAX_ORDER; i++)
58282199Sdumbbell		memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
59235783Skib
60235783Skib	return 0;
61235783Skib}
62235783Skib
63282199Sdumbbell/**
64282199Sdumbbell * Cleanup the DMA resources.
65282199Sdumbbell *
66282199Sdumbbell * \param dev DRM device.
67282199Sdumbbell *
68282199Sdumbbell * Free all pages associated with DMA buffers, the buffers and pages lists, and
69282199Sdumbbell * finally the drm_device::dma structure itself.
70282199Sdumbbell */
71235783Skibvoid drm_dma_takedown(struct drm_device *dev)
72235783Skib{
73282199Sdumbbell	struct drm_device_dma *dma = dev->dma;
74282199Sdumbbell	int i, j;
75235783Skib
76282199Sdumbbell	if (!dma)
77235783Skib		return;
78235783Skib
79235783Skib	/* Clear dma buffers */
80235783Skib	for (i = 0; i <= DRM_MAX_ORDER; i++) {
81235783Skib		if (dma->bufs[i].seg_count) {
82235783Skib			DRM_DEBUG("order %d: buf_count = %d,"
83282199Sdumbbell				  " seg_count = %d\n",
84282199Sdumbbell				  i,
85282199Sdumbbell				  dma->bufs[i].buf_count,
86282199Sdumbbell				  dma->bufs[i].seg_count);
87235783Skib			for (j = 0; j < dma->bufs[i].seg_count; j++) {
88282199Sdumbbell				if (dma->bufs[i].seglist[j]) {
89282199Sdumbbell					drm_pci_free(dev, dma->bufs[i].seglist[j]);
90282199Sdumbbell				}
91235783Skib			}
92235783Skib			free(dma->bufs[i].seglist, DRM_MEM_SEGS);
93235783Skib		}
94282199Sdumbbell		if (dma->bufs[i].buf_count) {
95282199Sdumbbell			for (j = 0; j < dma->bufs[i].buf_count; j++) {
96235783Skib				free(dma->bufs[i].buflist[j].dev_private,
97235783Skib				    DRM_MEM_BUFS);
98235783Skib			}
99282199Sdumbbell			free(dma->bufs[i].buflist, DRM_MEM_BUFS);
100235783Skib		}
101235783Skib	}
102235783Skib
103235783Skib	free(dma->buflist, DRM_MEM_BUFS);
104235783Skib	free(dma->pagelist, DRM_MEM_PAGES);
105235783Skib	free(dev->dma, DRM_MEM_DRIVER);
106235783Skib	dev->dma = NULL;
107235783Skib}
108235783Skib
109282199Sdumbbell/**
110282199Sdumbbell * Free a buffer.
111282199Sdumbbell *
112282199Sdumbbell * \param dev DRM device.
113282199Sdumbbell * \param buf buffer to free.
114282199Sdumbbell *
115282199Sdumbbell * Resets the fields of \p buf.
116282199Sdumbbell */
117282199Sdumbbellvoid drm_free_buffer(struct drm_device *dev, struct drm_buf * buf)
118235783Skib{
119235783Skib	if (!buf)
120235783Skib		return;
121235783Skib
122282199Sdumbbell	buf->waiting = 0;
123282199Sdumbbell	buf->pending = 0;
124282199Sdumbbell	buf->file_priv = NULL;
125282199Sdumbbell	buf->used = 0;
126235783Skib}
127235783Skib
128282199Sdumbbell/**
129282199Sdumbbell * Reclaim the buffers.
130282199Sdumbbell *
131282199Sdumbbell * \param file_priv DRM file private.
132282199Sdumbbell *
133282199Sdumbbell * Frees each buffer associated with \p file_priv not already on the hardware.
134282199Sdumbbell */
135282199Sdumbbellvoid drm_core_reclaim_buffers(struct drm_device *dev,
136282199Sdumbbell			      struct drm_file *file_priv)
137235783Skib{
138282199Sdumbbell	struct drm_device_dma *dma = dev->dma;
139282199Sdumbbell	int i;
140235783Skib
141235783Skib	if (!dma)
142235783Skib		return;
143235783Skib	for (i = 0; i < dma->buf_count; i++) {
144235783Skib		if (dma->buflist[i]->file_priv == file_priv) {
145235783Skib			switch (dma->buflist[i]->list) {
146235783Skib			case DRM_LIST_NONE:
147235783Skib				drm_free_buffer(dev, dma->buflist[i]);
148235783Skib				break;
149235783Skib			case DRM_LIST_WAIT:
150235783Skib				dma->buflist[i]->list = DRM_LIST_RECLAIM;
151235783Skib				break;
152235783Skib			default:
153235783Skib				/* Buffer already on hardware. */
154235783Skib				break;
155235783Skib			}
156235783Skib		}
157235783Skib	}
158235783Skib}
159235783Skib
160282199SdumbbellEXPORT_SYMBOL(drm_core_reclaim_buffers);
161