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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm/] [drm_scatter.h] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
2
 * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
3
 *
4
 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5
 * All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice (including the next
15
 * paragraph) shall be included in all copies or substantial portions of the
16
 * Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
 * DEALINGS IN THE SOFTWARE.
25
 *
26
 * Authors:
27
 *   Gareth Hughes <gareth@valinux.com>
28
 */
29
 
30
#include <linux/config.h>
31
#include <linux/vmalloc.h>
32
#include "drmP.h"
33
 
34
#define DEBUG_SCATTER 0
35
 
36
void DRM(sg_cleanup)( drm_sg_mem_t *entry )
37
{
38
        struct page *page;
39
        int i;
40
 
41
        for ( i = 0 ; i < entry->pages ; i++ ) {
42
                page = entry->pagelist[i];
43
                if ( page )
44
                        ClearPageReserved( page );
45
        }
46
 
47
        vfree( entry->virtual );
48
 
49
        DRM(free)( entry->busaddr,
50
                   entry->pages * sizeof(*entry->busaddr),
51
                   DRM_MEM_PAGES );
52
        DRM(free)( entry->pagelist,
53
                   entry->pages * sizeof(*entry->pagelist),
54
                   DRM_MEM_PAGES );
55
        DRM(free)( entry,
56
                   sizeof(*entry),
57
                   DRM_MEM_SGLISTS );
58
}
59
 
60
int DRM(sg_alloc)( struct inode *inode, struct file *filp,
61
                   unsigned int cmd, unsigned long arg )
62
{
63
        drm_file_t *priv = filp->private_data;
64
        drm_device_t *dev = priv->dev;
65
        drm_scatter_gather_t request;
66
        drm_sg_mem_t *entry;
67
        unsigned long pages, i, j;
68
 
69
        DRM_DEBUG( "%s\n", __FUNCTION__ );
70
 
71
        if ( dev->sg )
72
                return -EINVAL;
73
 
74
        if ( copy_from_user( &request,
75
                             (drm_scatter_gather_t *)arg,
76
                             sizeof(request) ) )
77
                return -EFAULT;
78
 
79
        entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
80
        if ( !entry )
81
                return -ENOMEM;
82
 
83
        memset( entry, 0, sizeof(*entry) );
84
 
85
        pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
86
        DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
87
 
88
        entry->pages = pages;
89
        entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist),
90
                                     DRM_MEM_PAGES );
91
        if ( !entry->pagelist ) {
92
                DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
93
                return -ENOMEM;
94
        }
95
 
96
        memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
97
 
98
        entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr),
99
                                     DRM_MEM_PAGES );
100
        if ( !entry->busaddr ) {
101
                DRM(free)( entry->pagelist,
102
                           entry->pages * sizeof(*entry->pagelist),
103
                           DRM_MEM_PAGES );
104
                DRM(free)( entry,
105
                           sizeof(*entry),
106
                           DRM_MEM_SGLISTS );
107
                return -ENOMEM;
108
        }
109
        memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
110
 
111
        entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
112
        if ( !entry->virtual ) {
113
                DRM(free)( entry->busaddr,
114
                           entry->pages * sizeof(*entry->busaddr),
115
                           DRM_MEM_PAGES );
116
                DRM(free)( entry->pagelist,
117
                           entry->pages * sizeof(*entry->pagelist),
118
                           DRM_MEM_PAGES );
119
                DRM(free)( entry,
120
                           sizeof(*entry),
121
                           DRM_MEM_SGLISTS );
122
                return -ENOMEM;
123
        }
124
 
125
        /* This also forces the mapping of COW pages, so our page list
126
         * will be valid.  Please don't remove it...
127
         */
128
        memset( entry->virtual, 0, pages << PAGE_SHIFT );
129
 
130
        entry->handle = (unsigned long)entry->virtual;
131
 
132
        DRM_DEBUG( "sg alloc handle  = %08lx\n", entry->handle );
133
        DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
134
 
135
        for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
136
                entry->pagelist[j] = vmalloc_to_page((void *)i);
137
                if (!entry->pagelist[j])
138
                        goto failed;
139
                SetPageReserved(entry->pagelist[j]);
140
        }
141
 
142
        request.handle = entry->handle;
143
 
144
        if ( copy_to_user( (drm_scatter_gather_t *)arg,
145
                           &request,
146
                           sizeof(request) ) ) {
147
                DRM(sg_cleanup)( entry );
148
                return -EFAULT;
149
        }
150
 
151
        dev->sg = entry;
152
 
153
#if DEBUG_SCATTER
154
        /* Verify that each page points to its virtual address, and vice
155
         * versa.
156
         */
157
        {
158
        int error = 0;
159
 
160
        for ( i = 0 ; i < pages ; i++ ) {
161
                unsigned long *tmp;
162
 
163
                tmp = page_address( entry->pagelist[i] );
164
                for ( j = 0 ;
165
                      j < PAGE_SIZE / sizeof(unsigned long) ;
166
                      j++, tmp++ ) {
167
                        *tmp = 0xcafebabe;
168
                }
169
                tmp = (unsigned long *)((u8 *)entry->virtual +
170
                                        (PAGE_SIZE * i));
171
                for( j = 0 ;
172
                     j < PAGE_SIZE / sizeof(unsigned long) ;
173
                     j++, tmp++ ) {
174
                        if ( *tmp != 0xcafebabe && error == 0 ) {
175
                                error = 1;
176
                                DRM_ERROR( "Scatter allocation error, "
177
                                           "pagelist does not match "
178
                                           "virtual mapping\n" );
179
                        }
180
                }
181
                tmp = page_address( entry->pagelist[i] );
182
                for(j = 0 ;
183
                    j < PAGE_SIZE / sizeof(unsigned long) ;
184
                    j++, tmp++) {
185
                        *tmp = 0;
186
                }
187
        }
188
        if (error == 0)
189
                DRM_ERROR( "Scatter allocation matches pagelist\n" );
190
        }
191
#endif
192
 
193
        return 0;
194
 
195
 failed:
196
        DRM(sg_cleanup)( entry );
197
        return -ENOMEM;
198
}
199
 
200
int DRM(sg_free)( struct inode *inode, struct file *filp,
201
                 unsigned int cmd, unsigned long arg )
202
{
203
        drm_file_t *priv = filp->private_data;
204
        drm_device_t *dev = priv->dev;
205
        drm_scatter_gather_t request;
206
        drm_sg_mem_t *entry;
207
 
208
        if ( copy_from_user( &request,
209
                             (drm_scatter_gather_t *)arg,
210
                             sizeof(request) ) )
211
                return -EFAULT;
212
 
213
        entry = dev->sg;
214
        dev->sg = NULL;
215
 
216
        if ( !entry || entry->handle != request.handle )
217
                return -EINVAL;
218
 
219
        DRM_DEBUG( "sg free virtual  = %p\n", entry->virtual );
220
 
221
        DRM(sg_cleanup)( entry );
222
 
223
        return 0;
224
}

powered by: WebSVN 2.1.0

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