OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm-4.0/] [r128_bufs.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* r128_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
2
 * Created: Wed Apr 12 16:19:08 2000 by kevin@precisioninsight.com
3
 *
4
 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
5
 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6
 * All Rights Reserved.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 * copy of this software and associated documentation files (the "Software"),
10
 * to deal in the Software without restriction, including without limitation
11
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
 * and/or sell copies of the Software, and to permit persons to whom the
13
 * Software is furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice (including the next
16
 * paragraph) shall be included in all copies or substantial portions of the
17
 * Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22
 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
 * DEALINGS IN THE SOFTWARE.
26
 *
27
 * Authors: Kevin E. Martin <martin@valinux.com>
28
 *          Rickard E. (Rik) Faith <faith@valinux.com>
29
 *          Jeff Hartmann <jhartmann@valinux.com>
30
 *
31
 */
32
 
33
#define __NO_VERSION__
34
#include <linux/config.h>
35
#include "drmP.h"
36
#include "r128_drv.h"
37
#include "linux/un.h"
38
 
39
 
40
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
41
int r128_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
42
                     unsigned long arg)
43
{
44
        drm_file_t       *priv = filp->private_data;
45
        drm_device_t     *dev  = priv->dev;
46
        drm_device_dma_t *dma  = dev->dma;
47
        drm_buf_desc_t    request;
48
        drm_buf_entry_t  *entry;
49
        drm_buf_t        *buf;
50
        unsigned long     offset;
51
        unsigned long     agp_offset;
52
        int               count;
53
        int               order;
54
        int               size;
55
        int               alignment;
56
        int               page_order;
57
        int               total;
58
        int               byte_count;
59
        int               i;
60
 
61
        if (!dma) return -EINVAL;
62
 
63
        if (copy_from_user(&request,
64
                           (drm_buf_desc_t *)arg,
65
                           sizeof(request)))
66
                return -EFAULT;
67
 
68
        count      = request.count;
69
        order      = drm_order(request.size);
70
        size       = 1 << order;
71
 
72
        alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
73
        page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
74
        total      = PAGE_SIZE << page_order;
75
 
76
        byte_count = 0;
77
        agp_offset = dev->agp->base + request.agp_start;
78
 
79
        DRM_DEBUG("count:      %d\n",  count);
80
        DRM_DEBUG("order:      %d\n",  order);
81
        DRM_DEBUG("size:       %d\n",  size);
82
        DRM_DEBUG("agp_offset: %ld\n", agp_offset);
83
        DRM_DEBUG("alignment:  %d\n",  alignment);
84
        DRM_DEBUG("page_order: %d\n",  page_order);
85
        DRM_DEBUG("total:      %d\n",  total);
86
 
87
        if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
88
        if (dev->queue_count) return -EBUSY; /* Not while in use */
89
 
90
        spin_lock(&dev->count_lock);
91
        if (dev->buf_use) {
92
                spin_unlock(&dev->count_lock);
93
                return -EBUSY;
94
        }
95
        atomic_inc(&dev->buf_alloc);
96
        spin_unlock(&dev->count_lock);
97
 
98
        down(&dev->struct_sem);
99
        entry = &dma->bufs[order];
100
        if (entry->buf_count) {
101
                up(&dev->struct_sem);
102
                atomic_dec(&dev->buf_alloc);
103
                return -ENOMEM; /* May only call once for each order */
104
        }
105
 
106
        /* Might be a poor limit, but take that up with XFree86
107
           if its a problem */
108
 
109
        if(count < 0 || count > 4096)
110
        {
111
                up(&dev->struct_sem);
112
                atomic_dec(&dev->buf_alloc);
113
                return -EINVAL;
114
        }
115
 
116
        entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
117
                                   DRM_MEM_BUFS);
118
        if (!entry->buflist) {
119
                up(&dev->struct_sem);
120
                atomic_dec(&dev->buf_alloc);
121
                return -ENOMEM;
122
        }
123
        memset(entry->buflist, 0, count * sizeof(*entry->buflist));
124
 
125
        entry->buf_size   = size;
126
        entry->page_order = page_order;
127
        offset            = 0;
128
 
129
        for (offset = 0;
130
             entry->buf_count < count;
131
             offset += alignment, ++entry->buf_count) {
132
                buf          = &entry->buflist[entry->buf_count];
133
                buf->idx     = dma->buf_count + entry->buf_count;
134
                buf->total   = alignment;
135
                buf->order   = order;
136
                buf->used    = 0;
137
                buf->offset  = (dma->byte_count + offset);
138
                buf->address = (void *)(agp_offset + offset);
139
                buf->next    = NULL;
140
                buf->waiting = 0;
141
                buf->pending = 0;
142
                init_waitqueue_head(&buf->dma_wait);
143
                buf->pid     = 0;
144
 
145
                buf->dev_priv_size = sizeof(drm_r128_buf_priv_t);
146
                buf->dev_private   = drm_alloc(sizeof(drm_r128_buf_priv_t),
147
                                               DRM_MEM_BUFS);
148
                memset(buf->dev_private, 0, buf->dev_priv_size);
149
 
150
#if DRM_DMA_HISTOGRAM
151
                buf->time_queued     = 0;
152
                buf->time_dispatched = 0;
153
                buf->time_completed  = 0;
154
                buf->time_freed      = 0;
155
#endif
156
 
157
                byte_count += PAGE_SIZE << page_order;
158
 
159
                DRM_DEBUG("buffer %d @ %p\n",
160
                          entry->buf_count, buf->address);
161
        }
162
 
163
        DRM_DEBUG("byte_count: %d\n", byte_count);
164
 
165
        dma->buflist = drm_realloc(dma->buflist,
166
                                   dma->buf_count * sizeof(*dma->buflist),
167
                                   (dma->buf_count + entry->buf_count)
168
                                   * sizeof(*dma->buflist),
169
                                   DRM_MEM_BUFS);
170
        for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
171
                dma->buflist[i] = &entry->buflist[i - dma->buf_count];
172
 
173
        dma->buf_count  += entry->buf_count;
174
        dma->byte_count += byte_count;
175
 
176
        drm_freelist_create(&entry->freelist, entry->buf_count);
177
        for (i = 0; i < entry->buf_count; i++) {
178
                drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
179
        }
180
 
181
        up(&dev->struct_sem);
182
 
183
        request.count = entry->buf_count;
184
        request.size  = size;
185
 
186
        if (copy_to_user((drm_buf_desc_t *)arg,
187
                         &request,
188
                         sizeof(request)))
189
                return -EFAULT;
190
 
191
        dma->flags = _DRM_DMA_USE_AGP;
192
 
193
        atomic_dec(&dev->buf_alloc);
194
        return 0;
195
}
196
#endif
197
 
198
int r128_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
199
                 unsigned long arg)
200
{
201
        drm_file_t              *priv           = filp->private_data;
202
        drm_device_t            *dev            = priv->dev;
203
        drm_r128_private_t      *dev_priv       = dev->dev_private;
204
        drm_buf_desc_t          request;
205
 
206
        if (!dev_priv || dev_priv->is_pci) return -EINVAL;
207
 
208
        if (copy_from_user(&request,
209
                           (drm_buf_desc_t *)arg,
210
                           sizeof(request)))
211
                return -EFAULT;
212
 
213
#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
214
        if (request.flags & _DRM_AGP_BUFFER)
215
                return r128_addbufs_agp(inode, filp, cmd, arg);
216
        else
217
#endif
218
                return -EINVAL;
219
}
220
 
221
int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
222
                 unsigned long arg)
223
{
224
        drm_file_t              *priv           = filp->private_data;
225
        drm_device_t            *dev            = priv->dev;
226
        drm_r128_private_t      *dev_priv       = dev->dev_private;
227
        drm_device_dma_t        *dma            = dev->dma;
228
        int                      retcode        = 0;
229
        const int                zero           = 0;
230
        unsigned long            virtual;
231
        unsigned long            address;
232
        drm_buf_map_t            request;
233
        int                      i;
234
 
235
        if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
236
 
237
        DRM_DEBUG("\n");
238
 
239
        spin_lock(&dev->count_lock);
240
        if (atomic_read(&dev->buf_alloc)) {
241
                spin_unlock(&dev->count_lock);
242
                return -EBUSY;
243
        }
244
        ++dev->buf_use;         /* Can't allocate more after this call */
245
        spin_unlock(&dev->count_lock);
246
 
247
        if (copy_from_user(&request,
248
                           (drm_buf_map_t *)arg,
249
                           sizeof(request)))
250
                return -EFAULT;
251
 
252
        if (request.count >= dma->buf_count) {
253
                if (dma->flags & _DRM_DMA_USE_AGP) {
254
                        drm_map_t *map;
255
 
256
                        map = dev_priv->buffers;
257
                        if (!map) {
258
                                retcode = -EINVAL;
259
                                goto done;
260
                        }
261
 
262
                        down_write(&current->mm->mmap_sem);
263
                        virtual = do_mmap(filp, 0, map->size,
264
                                          PROT_READ|PROT_WRITE,
265
                                          MAP_SHARED,
266
                                          (unsigned long)map->offset);
267
                        up_write(&current->mm->mmap_sem);
268
                } else {
269
                        down_write(&current->mm->mmap_sem);
270
                        virtual = do_mmap(filp, 0, dma->byte_count,
271
                                          PROT_READ|PROT_WRITE, MAP_SHARED, 0);
272
                        up_write(&current->mm->mmap_sem);
273
                }
274
                if (virtual > -1024UL) {
275
                        /* Real error */
276
                        retcode = (signed long)virtual;
277
                        goto done;
278
                }
279
                request.virtual = (void *)virtual;
280
 
281
                for (i = 0; i < dma->buf_count; i++) {
282
                        if (copy_to_user(&request.list[i].idx,
283
                                         &dma->buflist[i]->idx,
284
                                         sizeof(request.list[0].idx))) {
285
                                retcode = -EFAULT;
286
                                goto done;
287
                        }
288
                        if (copy_to_user(&request.list[i].total,
289
                                         &dma->buflist[i]->total,
290
                                         sizeof(request.list[0].total))) {
291
                                retcode = -EFAULT;
292
                                goto done;
293
                        }
294
                        if (copy_to_user(&request.list[i].used,
295
                                         &zero,
296
                                         sizeof(zero))) {
297
                                retcode = -EFAULT;
298
                                goto done;
299
                        }
300
                        address = virtual + dma->buflist[i]->offset;
301
                        if (copy_to_user(&request.list[i].address,
302
                                         &address,
303
                                         sizeof(address))) {
304
                                retcode = -EFAULT;
305
                                goto done;
306
                        }
307
                }
308
        }
309
 done:
310
        request.count = dma->buf_count;
311
        DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
312
 
313
        if (copy_to_user((drm_buf_map_t *)arg,
314
                         &request,
315
                         sizeof(request)))
316
                return -EFAULT;
317
 
318
        return retcode;
319
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.