1145132Sanholt/*-
2145132Sanholt * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
3145132Sanholt * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
4145132Sanholt * All Rights Reserved.
5145132Sanholt *
6145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a
7145132Sanholt * copy of this software and associated documentation files (the "Software"),
8145132Sanholt * to deal in the Software without restriction, including without limitation
9145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the
11145132Sanholt * Software is furnished to do so, subject to the following conditions:
12145132Sanholt *
13145132Sanholt * The above copyright notice and this permission notice (including the next
14145132Sanholt * paragraph) shall be included in all copies or substantial portions of the
15145132Sanholt * Software.
16145132Sanholt *
17145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20145132Sanholt * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21145132Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22145132Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23145132Sanholt * OTHER DEALINGS IN THE SOFTWARE.
24145132Sanholt *
25145132Sanholt * Authors:
26145132Sanholt *    Rickard E. (Rik) Faith <faith@valinux.com>
27145132Sanholt *    Gareth Hughes <gareth@valinux.com>
28145132Sanholt *
29145132Sanholt */
30145132Sanholt
31152909Sanholt#include <sys/cdefs.h>
32152909Sanholt__FBSDID("$FreeBSD$");
33152909Sanholt
34182080Srnoland/** @file drm_dma.c
35182080Srnoland * Support code for DMA buffer management.
36182080Srnoland *
37182080Srnoland * The implementation used to be significantly more complicated, but the
38182080Srnoland * complexity has been moved into the drivers as different buffer management
39182080Srnoland * schemes evolved.
40182080Srnoland */
41182080Srnoland
42145132Sanholt#include "dev/drm/drmP.h"
43145132Sanholt
44182080Srnolandint drm_dma_setup(struct drm_device *dev)
45145132Sanholt{
46145132Sanholt
47183833Srnoland	dev->dma = malloc(sizeof(*dev->dma), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
48145132Sanholt	if (dev->dma == NULL)
49182080Srnoland		return ENOMEM;
50145132Sanholt
51182080Srnoland	DRM_SPININIT(&dev->dma_lock, "drmdma");
52145132Sanholt
53145132Sanholt	return 0;
54145132Sanholt}
55145132Sanholt
56182080Srnolandvoid drm_dma_takedown(struct drm_device *dev)
57145132Sanholt{
58145132Sanholt	drm_device_dma_t  *dma = dev->dma;
59145132Sanholt	int		  i, j;
60145132Sanholt
61145132Sanholt	if (dma == NULL)
62145132Sanholt		return;
63145132Sanholt
64183573Srnoland	/* Clear dma buffers */
65145132Sanholt	for (i = 0; i <= DRM_MAX_ORDER; i++) {
66145132Sanholt		if (dma->bufs[i].seg_count) {
67145132Sanholt			DRM_DEBUG("order %d: buf_count = %d,"
68183573Srnoland			    " seg_count = %d\n", i, dma->bufs[i].buf_count,
69183573Srnoland			    dma->bufs[i].seg_count);
70145132Sanholt			for (j = 0; j < dma->bufs[i].seg_count; j++) {
71152909Sanholt				drm_pci_free(dev, dma->bufs[i].seglist[j]);
72145132Sanholt			}
73183833Srnoland			free(dma->bufs[i].seglist, DRM_MEM_SEGS);
74145132Sanholt		}
75145132Sanholt
76145132Sanholt	   	if (dma->bufs[i].buf_count) {
77145132Sanholt		   	for (j = 0; j < dma->bufs[i].buf_count; j++) {
78145132Sanholt				free(dma->bufs[i].buflist[j].dev_private,
79183833Srnoland				    DRM_MEM_BUFS);
80145132Sanholt			}
81183833Srnoland		   	free(dma->bufs[i].buflist, DRM_MEM_BUFS);
82145132Sanholt		}
83145132Sanholt	}
84145132Sanholt
85183833Srnoland	free(dma->buflist, DRM_MEM_BUFS);
86183833Srnoland	free(dma->pagelist, DRM_MEM_PAGES);
87183833Srnoland	free(dev->dma, DRM_MEM_DRIVER);
88145132Sanholt	dev->dma = NULL;
89182080Srnoland	DRM_SPINUNINIT(&dev->dma_lock);
90145132Sanholt}
91145132Sanholt
92145132Sanholt
93182080Srnolandvoid drm_free_buffer(struct drm_device *dev, drm_buf_t *buf)
94145132Sanholt{
95183573Srnoland	if (!buf)
96183573Srnoland		return;
97145132Sanholt
98145132Sanholt	buf->pending  = 0;
99182080Srnoland	buf->file_priv= NULL;
100145132Sanholt	buf->used     = 0;
101145132Sanholt}
102145132Sanholt
103182080Srnolandvoid drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
104145132Sanholt{
105145132Sanholt	drm_device_dma_t *dma = dev->dma;
106145132Sanholt	int		 i;
107145132Sanholt
108183573Srnoland	if (!dma)
109183573Srnoland		return;
110183573Srnoland
111145132Sanholt	for (i = 0; i < dma->buf_count; i++) {
112182080Srnoland		if (dma->buflist[i]->file_priv == file_priv) {
113145132Sanholt			switch (dma->buflist[i]->list) {
114145132Sanholt			case DRM_LIST_NONE:
115145132Sanholt				drm_free_buffer(dev, dma->buflist[i]);
116145132Sanholt				break;
117145132Sanholt			case DRM_LIST_WAIT:
118145132Sanholt				dma->buflist[i]->list = DRM_LIST_RECLAIM;
119145132Sanholt				break;
120145132Sanholt			default:
121145132Sanholt				/* Buffer already on hardware. */
122145132Sanholt				break;
123145132Sanholt			}
124145132Sanholt		}
125145132Sanholt	}
126145132Sanholt}
127145132Sanholt
128145132Sanholt/* Call into the driver-specific DMA handler */
129182080Srnolandint drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv)
130145132Sanholt{
131145132Sanholt
132183573Srnoland	if (dev->driver->dma_ioctl) {
133182080Srnoland		/* shared code returns -errno */
134183573Srnoland		return -dev->driver->dma_ioctl(dev, data, file_priv);
135145132Sanholt	} else {
136145132Sanholt		DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
137145132Sanholt		return EINVAL;
138145132Sanholt	}
139145132Sanholt}
140