~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* drm_drv.h -- Generic driver template -*- linux-c -*-
 
2
 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
 
3
 *
 
4
 * Copyright 1999, 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
 * VA LINUX SYSTEMS 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
 
25
 * OTHER DEALINGS IN THE SOFTWARE.
 
26
 *
 
27
 * Authors:
 
28
 *    Rickard E. (Rik) Faith <faith@valinux.com>
 
29
 *    Gareth Hughes <gareth@valinux.com>
 
30
 */
 
31
 
 
32
/*
 
33
 * To use this template, you must at least define the following (samples
 
34
 * given for the MGA driver):
 
35
 *
 
36
 * #define DRIVER_AUTHOR        "VA Linux Systems, Inc."
 
37
 *
 
38
 * #define DRIVER_NAME          "mga"
 
39
 * #define DRIVER_DESC          "Matrox G200/G400"
 
40
 * #define DRIVER_DATE          "20001127"
 
41
 *
 
42
 * #define DRIVER_MAJOR         2
 
43
 * #define DRIVER_MINOR         0
 
44
 * #define DRIVER_PATCHLEVEL    2
 
45
 *
 
46
 * #define DRIVER_IOCTL_COUNT   DRM_ARRAY_SIZE( mga_ioctls )
 
47
 *
 
48
 * #define DRM(x)               mga_##x
 
49
 */
 
50
 
 
51
#ifndef __MUST_HAVE_AGP
 
52
#define __MUST_HAVE_AGP                 0
 
53
#endif
 
54
#ifndef __HAVE_CTX_BITMAP
 
55
#define __HAVE_CTX_BITMAP               0
 
56
#endif
 
57
#ifndef __HAVE_DMA_IRQ
 
58
#define __HAVE_DMA_IRQ                  0
 
59
#endif
 
60
#ifndef __HAVE_DMA_QUEUE
 
61
#define __HAVE_DMA_QUEUE                0
 
62
#endif
 
63
#ifndef __HAVE_MULTIPLE_DMA_QUEUES
 
64
#define __HAVE_MULTIPLE_DMA_QUEUES      0
 
65
#endif
 
66
#ifndef __HAVE_DMA_SCHEDULE
 
67
#define __HAVE_DMA_SCHEDULE             0
 
68
#endif
 
69
#ifndef __HAVE_DMA_FLUSH
 
70
#define __HAVE_DMA_FLUSH                0
 
71
#endif
 
72
#ifndef __HAVE_DMA_READY
 
73
#define __HAVE_DMA_READY                0
 
74
#endif
 
75
#ifndef __HAVE_DMA_QUIESCENT
 
76
#define __HAVE_DMA_QUIESCENT            0
 
77
#endif
 
78
#ifndef __HAVE_RELEASE
 
79
#define __HAVE_RELEASE                  0
 
80
#endif
 
81
#ifndef __HAVE_COUNTERS
 
82
#define __HAVE_COUNTERS                 0
 
83
#endif
 
84
#ifndef __HAVE_SG
 
85
#define __HAVE_SG                       0
 
86
#endif
 
87
#ifndef __HAVE_KERNEL_CTX_SWITCH
 
88
#define __HAVE_KERNEL_CTX_SWITCH        0
 
89
#endif
 
90
#ifndef PCI_ANY_ID
 
91
#define PCI_ANY_ID      ~0
 
92
#endif
 
93
 
 
94
#ifndef DRIVER_PREINIT
 
95
#define DRIVER_PREINIT()
 
96
#endif
 
97
#ifndef DRIVER_POSTINIT
 
98
#define DRIVER_POSTINIT()
 
99
#endif
 
100
#ifndef DRIVER_PRERELEASE
 
101
#define DRIVER_PRERELEASE()
 
102
#endif
 
103
#ifndef DRIVER_PRETAKEDOWN
 
104
#define DRIVER_PRETAKEDOWN()
 
105
#endif
 
106
#ifndef DRIVER_POSTCLEANUP
 
107
#define DRIVER_POSTCLEANUP()
 
108
#endif
 
109
#ifndef DRIVER_PRESETUP
 
110
#define DRIVER_PRESETUP()
 
111
#endif
 
112
#ifndef DRIVER_POSTSETUP
 
113
#define DRIVER_POSTSETUP()
 
114
#endif
 
115
#ifndef DRIVER_IOCTLS
 
116
#define DRIVER_IOCTLS
 
117
#endif
 
118
#ifndef DRIVER_FOPS
 
119
#endif
 
120
 
 
121
/*
 
122
 * The default number of instances (minor numbers) to initialize.
 
123
 */
 
124
#ifndef DRIVER_NUM_CARDS
 
125
#define DRIVER_NUM_CARDS 1
 
126
#endif
 
127
 
 
128
#ifdef __FreeBSD__
 
129
static int DRM(init)(device_t nbdev);
 
130
static void DRM(cleanup)(device_t nbdev);
 
131
#elif defined(__NetBSD__)
 
132
static int DRM(init)(drm_device_t *);
 
133
static void DRM(cleanup)(drm_device_t *);
 
134
#endif
 
135
 
 
136
#ifdef __FreeBSD__
 
137
#define CDEV_MAJOR      145
 
138
#define DRIVER_SOFTC(unit) \
 
139
        ((drm_device_t *) devclass_get_softc(DRM(devclass), unit))
 
140
 
 
141
#if __REALLY_HAVE_AGP
 
142
MODULE_DEPEND(DRIVER_NAME, agp, 1, 1, 1);
 
143
#endif
 
144
#if DRM_LINUX
 
145
MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1);
 
146
#endif
 
147
#endif /* __FreeBSD__ */
 
148
 
 
149
#ifdef __NetBSD__
 
150
#define CDEV_MAJOR      90
 
151
#define DRIVER_SOFTC(unit) \
 
152
        ((drm_device_t *) device_lookup(&DRM(_cd), unit))
 
153
#endif /* __NetBSD__ */
 
154
 
 
155
static drm_ioctl_desc_t           DRM(ioctls)[] = {
 
156
        [DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { DRM(version),     0, 0 },
 
157
        [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { DRM(getunique),   0, 0 },
 
158
        [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { DRM(getmagic),    0, 0 },
 
159
        [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_busid),   0, 1 },
 
160
        [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { DRM(getmap),      0, 0 },
 
161
        [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { DRM(getclient),   0, 0 },
 
162
        [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { DRM(getstats),    0, 0 },
 
163
 
 
164
        [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { DRM(setunique),   1, 1 },
 
165
        [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]         = { DRM(block),       1, 1 },
 
166
        [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { DRM(unblock),     1, 1 },
 
167
        [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]    = { DRM(authmagic),   1, 1 },
 
168
 
 
169
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { DRM(addmap),      1, 1 },
 
170
        [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { DRM(rmmap),       1, 0 },
 
171
 
 
172
#if __HAVE_CTX_BITMAP
 
173
        [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
 
174
        [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
 
175
#endif
 
176
 
 
177
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { DRM(addctx),      1, 1 },
 
178
        [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { DRM(rmctx),       1, 1 },
 
179
        [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]       = { DRM(modctx),      1, 1 },
 
180
        [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]       = { DRM(getctx),      1, 0 },
 
181
        [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]    = { DRM(switchctx),   1, 1 },
 
182
        [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]       = { DRM(newctx),      1, 1 },
 
183
        [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]       = { DRM(resctx),      1, 0 },
 
184
 
 
185
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]      = { DRM(adddraw),     1, 1 },
 
186
        [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]       = { DRM(rmdraw),      1, 1 },
 
187
 
 
188
        [DRM_IOCTL_NR(DRM_IOCTL_LOCK)]          = { DRM(lock),        1, 0 },
 
189
        [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { DRM(unlock),      1, 0 },
 
190
        [DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { DRM(finish),      1, 0 },
 
191
 
 
192
#if __HAVE_DMA
 
193
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { DRM(addbufs),     1, 1 },
 
194
        [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { DRM(markbufs),    1, 1 },
 
195
        [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { DRM(infobufs),    1, 0 },
 
196
        [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { DRM(mapbufs),     1, 0 },
 
197
        [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { DRM(freebufs),    1, 0 },
 
198
 
 
199
        /* The DRM_IOCTL_DMA ioctl should be defined by the driver.
 
200
         */
 
201
        [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
 
202
#endif
 
203
 
 
204
#if __REALLY_HAVE_AGP
 
205
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { DRM(agp_acquire), 1, 1 },
 
206
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { DRM(agp_release), 1, 1 },
 
207
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { DRM(agp_enable),  1, 1 },
 
208
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { DRM(agp_info),    1, 0 },
 
209
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { DRM(agp_alloc),   1, 1 },
 
210
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { DRM(agp_free),    1, 1 },
 
211
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { DRM(agp_bind),    1, 1 },
 
212
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind),  1, 1 },
 
213
#endif
 
214
 
 
215
#if __HAVE_SG
 
216
        [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { DRM(sg_alloc),    1, 1 },
 
217
        [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
 
218
#endif
 
219
 
 
220
#if __HAVE_VBL_IRQ
 
221
        [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { DRM(wait_vblank), 0, 0 },
 
222
#endif
 
223
 
 
224
        DRIVER_IOCTLS
 
225
};
 
226
 
 
227
#define DRIVER_IOCTL_COUNT      DRM_ARRAY_SIZE( DRM(ioctls) )
 
228
 
 
229
const char *DRM(find_description)(int vendor, int device);
 
230
 
 
231
#ifdef __FreeBSD__
 
232
static int DRM(probe)(device_t dev)
 
233
{
 
234
        const char *s = NULL;
 
235
 
 
236
        int pciid=pci_get_devid(dev);
 
237
        int vendor = (pciid & 0x0000ffff);
 
238
        int device = (pciid & 0xffff0000) >> 16;
 
239
        
 
240
        s = DRM(find_description)(vendor, device);
 
241
        if (s) {
 
242
                device_set_desc(dev, s);
 
243
                return 0;
 
244
        }
 
245
 
 
246
        return ENXIO;
 
247
}
 
248
 
 
249
static int DRM(attach)(device_t dev)
 
250
{
 
251
        return DRM(init)(dev);
 
252
}
 
253
 
 
254
static int DRM(detach)(device_t dev)
 
255
{
 
256
        DRM(cleanup)(dev);
 
257
        return 0;
 
258
}
 
259
static device_method_t DRM(methods)[] = {
 
260
        /* Device interface */
 
261
        DEVMETHOD(device_probe,         DRM( probe)),
 
262
        DEVMETHOD(device_attach,        DRM( attach)),
 
263
        DEVMETHOD(device_detach,        DRM( detach)),
 
264
 
 
265
        { 0, 0 }
 
266
};
 
267
 
 
268
static driver_t DRM(driver) = {
 
269
        "drm",
 
270
        DRM(methods),
 
271
        sizeof(drm_device_t),
 
272
};
 
273
 
 
274
static devclass_t DRM( devclass);
 
275
 
 
276
static struct cdevsw DRM( cdevsw) = {
 
277
        /* open */      DRM( open ),
 
278
        /* close */     DRM( close ),
 
279
        /* read */      DRM( read ),
 
280
        /* write */     DRM( write ),
 
281
        /* ioctl */     DRM( ioctl ),
 
282
        /* poll */      DRM( poll ),
 
283
        /* mmap */      DRM( mmap ),
 
284
        /* strategy */  nostrategy,
 
285
        /* name */      DRIVER_NAME,
 
286
        /* maj */       CDEV_MAJOR,
 
287
        /* dump */      nodump,
 
288
        /* psize */     nopsize,
 
289
        /* flags */     D_TTY | D_TRACKCLOSE,
 
290
#if __FreeBSD_version >= 500000
 
291
        /* kqfilter */  0
 
292
#else
 
293
        /* bmaj */      -1
 
294
#endif
 
295
};
 
296
 
 
297
#elif defined(__NetBSD__)
 
298
int DRM(probe)(struct device *parent, struct cfdata *match, void *aux);
 
299
void DRM(attach)(struct device *parent, struct device *self, void *aux);
 
300
int DRM(detach)(struct device *self, int flags);
 
301
int DRM(activate)(struct device *self, enum devact act);
 
302
 
 
303
struct cfattach DRM(_ca) = {
 
304
        sizeof(drm_device_t), DRM(probe), 
 
305
        DRM(attach), DRM(detach), DRM(activate) };
 
306
        
 
307
int DRM(probe)(struct device *parent, struct cfdata *match, void *aux)
 
308
{
 
309
        struct pci_attach_args *pa = aux;
 
310
        const char *desc;
 
311
 
 
312
        desc = DRM(find_description)(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id));
 
313
        if (desc != NULL)
 
314
                return 10;
 
315
        return 0;
 
316
}
 
317
 
 
318
void DRM(attach)(struct device *parent, struct device *self, void *aux)
 
319
{
 
320
        struct pci_attach_args *pa = aux;
 
321
        drm_device_t *dev = (drm_device_t *)self;
 
322
        
 
323
        memcpy(&dev->pa, aux, sizeof(dev->pa));
 
324
        
 
325
        DRM_INFO("%s", DRM(find_description)(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id)));
 
326
        DRM(init)(dev);
 
327
}
 
328
 
 
329
int DRM(detach)(struct device *self, int flags)
 
330
{
 
331
        DRM(cleanup)((drm_device_t *)self);
 
332
        return 0;
 
333
}
 
334
 
 
335
int DRM(activate)(struct device *self, enum devact act)
 
336
{
 
337
        switch (act) {
 
338
        case DVACT_ACTIVATE:
 
339
                return (EOPNOTSUPP);
 
340
                break;
 
341
 
 
342
        case DVACT_DEACTIVATE:
 
343
                /* FIXME */
 
344
                break;
 
345
        }
 
346
        return (0);
 
347
}
 
348
 
 
349
#endif
 
350
 
 
351
const char *DRM(find_description)(int vendor, int device) {
 
352
        const char *s = NULL;
 
353
        int i=0, done=0;
 
354
        
 
355
        while ( !done && (DRM(devicelist)[i].vendor != 0 ) ) {
 
356
                if ( (DRM(devicelist)[i].vendor == vendor) &&
 
357
                     (DRM(devicelist)[i].device == device) ) {
 
358
                        done=1;
 
359
                        if ( DRM(devicelist)[i].supported )
 
360
                                s = DRM(devicelist)[i].name;
 
361
                        else
 
362
                                DRM_INFO("%s not supported\n", DRM(devicelist)[i].name);
 
363
                }
 
364
                i++;
 
365
        }
 
366
        return s;
 
367
}
 
368
 
 
369
static int DRM(setup)( drm_device_t *dev )
 
370
{
 
371
        int i;
 
372
 
 
373
        DRIVER_PRESETUP();
 
374
        atomic_set( &dev->ioctl_count, 0 );
 
375
        atomic_set( &dev->vma_count, 0 );
 
376
        dev->buf_use = 0;
 
377
        atomic_set( &dev->buf_alloc, 0 );
 
378
 
 
379
#if __HAVE_DMA
 
380
        i = DRM(dma_setup)( dev );
 
381
        if ( i < 0 )
 
382
                return i;
 
383
#endif
 
384
 
 
385
        dev->counters  = 6 + __HAVE_COUNTERS;
 
386
        dev->types[0]  = _DRM_STAT_LOCK;
 
387
        dev->types[1]  = _DRM_STAT_OPENS;
 
388
        dev->types[2]  = _DRM_STAT_CLOSES;
 
389
        dev->types[3]  = _DRM_STAT_IOCTLS;
 
390
        dev->types[4]  = _DRM_STAT_LOCKS;
 
391
        dev->types[5]  = _DRM_STAT_UNLOCKS;
 
392
#ifdef __HAVE_COUNTER6
 
393
        dev->types[6]  = __HAVE_COUNTER6;
 
394
#endif
 
395
#ifdef __HAVE_COUNTER7
 
396
        dev->types[7]  = __HAVE_COUNTER7;
 
397
#endif
 
398
#ifdef __HAVE_COUNTER8
 
399
        dev->types[8]  = __HAVE_COUNTER8;
 
400
#endif
 
401
#ifdef __HAVE_COUNTER9
 
402
        dev->types[9]  = __HAVE_COUNTER9;
 
403
#endif
 
404
#ifdef __HAVE_COUNTER10
 
405
        dev->types[10] = __HAVE_COUNTER10;
 
406
#endif
 
407
#ifdef __HAVE_COUNTER11
 
408
        dev->types[11] = __HAVE_COUNTER11;
 
409
#endif
 
410
#ifdef __HAVE_COUNTER12
 
411
        dev->types[12] = __HAVE_COUNTER12;
 
412
#endif
 
413
#ifdef __HAVE_COUNTER13
 
414
        dev->types[13] = __HAVE_COUNTER13;
 
415
#endif
 
416
#ifdef __HAVE_COUNTER14
 
417
        dev->types[14] = __HAVE_COUNTER14;
 
418
#endif
 
419
#ifdef __HAVE_COUNTER15
 
420
        dev->types[14] = __HAVE_COUNTER14;
 
421
#endif
 
422
 
 
423
        for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
 
424
                atomic_set( &dev->counts[i], 0 );
 
425
 
 
426
        for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
 
427
                dev->magiclist[i].head = NULL;
 
428
                dev->magiclist[i].tail = NULL;
 
429
        }
 
430
 
 
431
        dev->maplist = DRM(alloc)(sizeof(*dev->maplist),
 
432
                                  DRM_MEM_MAPS);
 
433
        if(dev->maplist == NULL) return DRM_ERR(ENOMEM);
 
434
        memset(dev->maplist, 0, sizeof(*dev->maplist));
 
435
        TAILQ_INIT(dev->maplist);
 
436
        dev->map_count = 0;
 
437
 
 
438
        dev->vmalist = NULL;
 
439
        dev->lock.hw_lock = NULL;
 
440
        dev->lock.lock_queue = 0;
 
441
        dev->queue_count = 0;
 
442
        dev->queue_reserved = 0;
 
443
        dev->queue_slots = 0;
 
444
        dev->queuelist = NULL;
 
445
        dev->irq = 0;
 
446
        dev->context_flag = 0;
 
447
        dev->interrupt_flag = 0;
 
448
        dev->dma_flag = 0;
 
449
        dev->last_context = 0;
 
450
        dev->last_switch = 0;
 
451
        dev->last_checked = 0;
 
452
#if __FreeBSD_version >= 500000
 
453
        callout_init( &dev->timer, 1 );
 
454
#else
 
455
        callout_init( &dev->timer );
 
456
#endif
 
457
        dev->context_wait = 0;
 
458
 
 
459
        dev->ctx_start = 0;
 
460
        dev->lck_start = 0;
 
461
 
 
462
        dev->buf_rp = dev->buf;
 
463
        dev->buf_wp = dev->buf;
 
464
        dev->buf_end = dev->buf + DRM_BSZ;
 
465
#ifdef __FreeBSD__
 
466
        dev->buf_sigio = NULL;
 
467
#elif defined(__NetBSD__)
 
468
        dev->buf_pgid = 0;
 
469
#endif
 
470
        dev->buf_readers = 0;
 
471
        dev->buf_writers = 0;
 
472
        dev->buf_selecting = 0;
 
473
 
 
474
        DRM_DEBUG( "\n" );
 
475
 
 
476
        /* The kernel's context could be created here, but is now created
 
477
         * in drm_dma_enqueue.  This is more resource-efficient for
 
478
         * hardware that does not do DMA, but may mean that
 
479
         * drm_select_queue fails between the time the interrupt is
 
480
         * initialized and the time the queues are initialized.
 
481
         */
 
482
        DRIVER_POSTSETUP();
 
483
        return 0;
 
484
}
 
485
 
 
486
 
 
487
static int DRM(takedown)( drm_device_t *dev )
 
488
{
 
489
        drm_magic_entry_t *pt, *next;
 
490
        drm_map_t *map;
 
491
        drm_map_list_entry_t *list;
 
492
        drm_vma_entry_t *vma, *vma_next;
 
493
        int i;
 
494
 
 
495
        DRM_DEBUG( "\n" );
 
496
 
 
497
        DRIVER_PRETAKEDOWN();
 
498
#if __HAVE_DMA_IRQ
 
499
        if ( dev->irq ) DRM(irq_uninstall)( dev );
 
500
#endif
 
501
 
 
502
        DRM_LOCK;
 
503
        callout_stop( &dev->timer );
 
504
 
 
505
        if ( dev->devname ) {
 
506
                DRM(free)( dev->devname, strlen( dev->devname ) + 1,
 
507
                           DRM_MEM_DRIVER );
 
508
                dev->devname = NULL;
 
509
        }
 
510
 
 
511
        if ( dev->unique ) {
 
512
                DRM(free)( dev->unique, strlen( dev->unique ) + 1,
 
513
                           DRM_MEM_DRIVER );
 
514
                dev->unique = NULL;
 
515
                dev->unique_len = 0;
 
516
        }
 
517
                                /* Clear pid list */
 
518
        for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
 
519
                for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
 
520
                        next = pt->next;
 
521
                        DRM(free)( pt, sizeof(*pt), DRM_MEM_MAGIC );
 
522
                }
 
523
                dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
 
524
        }
 
525
 
 
526
#if __REALLY_HAVE_AGP
 
527
                                /* Clear AGP information */
 
528
        if ( dev->agp ) {
 
529
                drm_agp_mem_t *entry;
 
530
                drm_agp_mem_t *nexte;
 
531
 
 
532
                                /* Remove AGP resources, but leave dev->agp
 
533
                                   intact until drv_cleanup is called. */
 
534
                for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
 
535
                        nexte = entry->next;
 
536
                        if ( entry->bound ) DRM(unbind_agp)( entry->handle );
 
537
                        DRM(free_agp)( entry->handle, entry->pages );
 
538
                        DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
 
539
                }
 
540
                dev->agp->memory = NULL;
 
541
 
 
542
                if ( dev->agp->acquired ) DRM(agp_do_release)();
 
543
 
 
544
                dev->agp->acquired = 0;
 
545
                dev->agp->enabled  = 0;
 
546
        }
 
547
#endif
 
548
 
 
549
                                /* Clear vma list (only built for debugging) */
 
550
        if ( dev->vmalist ) {
 
551
                for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
 
552
                        vma_next = vma->next;
 
553
                        DRM(free)( vma, sizeof(*vma), DRM_MEM_VMAS );
 
554
                }
 
555
                dev->vmalist = NULL;
 
556
        }
 
557
 
 
558
        if( dev->maplist ) {
 
559
                while ((list=TAILQ_FIRST(dev->maplist))) {
 
560
                        map = list->map;
 
561
                        switch ( map->type ) {
 
562
                        case _DRM_REGISTERS:
 
563
                        case _DRM_FRAME_BUFFER:
 
564
#if __REALLY_HAVE_MTRR
 
565
                                if ( map->mtrr >= 0 ) {
 
566
                                        int retcode;
 
567
#ifdef __FreeBSD__
 
568
                                        int act;
 
569
                                        struct mem_range_desc mrdesc;
 
570
                                        mrdesc.mr_base = map->offset;
 
571
                                        mrdesc.mr_len = map->size;
 
572
                                        mrdesc.mr_flags = MDF_WRITECOMBINE;
 
573
                                        act = MEMRANGE_SET_UPDATE;
 
574
                                        bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME));
 
575
                                        retcode = mem_range_attr_set(&mrdesc, &act);
 
576
                                        map->mtrr=1;
 
577
#elif defined __NetBSD__
 
578
                                        struct mtrr mtrrmap;
 
579
                                        int one = 1;
 
580
                                        mtrrmap.base = map->offset;
 
581
                                        mtrrmap.len = map->size;
 
582
                                        mtrrmap.type = MTRR_TYPE_WC;
 
583
                                        mtrrmap.flags = 0;
 
584
                                        /*mtrrmap.owner = p->p_pid;*/
 
585
                                        /* XXX: Use curproc here? */
 
586
                                        retcode = mtrr_set( &mtrrmap, &one, 
 
587
                                                DRM_CURPROC, MTRR_GETSET_KERNEL);
 
588
#endif
 
589
                                        DRM_DEBUG( "mtrr_del=%d\n", retcode );
 
590
                                }
 
591
#endif
 
592
                                DRM(ioremapfree)( map->handle, map->size );
 
593
                                break;
 
594
                        case _DRM_SHM:
 
595
                                DRM(free)(map->handle,
 
596
                                               map->size,
 
597
                                               DRM_MEM_SAREA);
 
598
                                break;
 
599
 
 
600
                        case _DRM_AGP:
 
601
                                /* Do nothing here, because this is all
 
602
                                 * handled in the AGP/GART driver.
 
603
                                 */
 
604
                                break;
 
605
                       case _DRM_SCATTER_GATHER:
 
606
                                /* Handle it, but do nothing, if REALLY_HAVE_SG
 
607
                                 * isn't defined.
 
608
                                 */
 
609
#if __REALLY_HAVE_SG
 
610
                                if(dev->sg) {
 
611
                                        DRM(sg_cleanup)(dev->sg);
 
612
                                        dev->sg = NULL;
 
613
                                }
 
614
#endif
 
615
                                break;
 
616
                        }
 
617
                        TAILQ_REMOVE(dev->maplist, list, link);
 
618
                        DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
 
619
                        DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
 
620
                }
 
621
                DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
 
622
                dev->maplist   = NULL;
 
623
        }
 
624
 
 
625
#if __HAVE_DMA_QUEUE || __HAVE_MULTIPLE_DMA_QUEUES
 
626
        if ( dev->queuelist ) {
 
627
                for ( i = 0 ; i < dev->queue_count ; i++ ) {
 
628
                        DRM(waitlist_destroy)( &dev->queuelist[i]->waitlist );
 
629
                        if ( dev->queuelist[i] ) {
 
630
                                DRM(free)( dev->queuelist[i],
 
631
                                          sizeof(*dev->queuelist[0]),
 
632
                                          DRM_MEM_QUEUES );
 
633
                                dev->queuelist[i] = NULL;
 
634
                        }
 
635
                }
 
636
                DRM(free)( dev->queuelist,
 
637
                          dev->queue_slots * sizeof(*dev->queuelist),
 
638
                          DRM_MEM_QUEUES );
 
639
                dev->queuelist = NULL;
 
640
        }
 
641
        dev->queue_count = 0;
 
642
#endif
 
643
 
 
644
#if __HAVE_DMA
 
645
        DRM(dma_takedown)( dev );
 
646
#endif
 
647
        if ( dev->lock.hw_lock ) {
 
648
                dev->lock.hw_lock = NULL; /* SHM removed */
 
649
                dev->lock.pid = 0;
 
650
                DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
 
651
        }
 
652
        DRM_UNLOCK;
 
653
 
 
654
        return 0;
 
655
}
 
656
 
 
657
/* linux: drm_init is called via init_module at module load time, or via
 
658
 *        linux/init/main.c (this is not currently supported).
 
659
 * bsd:   drm_init is called via the attach function per device.
 
660
 */
 
661
#ifdef __FreeBSD__
 
662
static int DRM(init)( device_t nbdev )
 
663
#elif defined(__NetBSD__)
 
664
static int DRM(init)( drm_device_t *dev )
 
665
#endif
 
666
{
 
667
        int unit;
 
668
#ifdef __FreeBSD__
 
669
        drm_device_t *dev;
 
670
#endif
 
671
#if __HAVE_CTX_BITMAP
 
672
        int retcode;
 
673
#endif
 
674
        DRM_DEBUG( "\n" );
 
675
        DRIVER_PREINIT();
 
676
 
 
677
#ifdef __FreeBSD__
 
678
        unit = device_get_unit(nbdev);
 
679
        dev = device_get_softc(nbdev);
 
680
        memset( (void *)dev, 0, sizeof(*dev) );
 
681
        dev->device = nbdev;
 
682
        dev->devnode = make_dev( &DRM(cdevsw),
 
683
                        unit,
 
684
                        DRM_DEV_UID,
 
685
                        DRM_DEV_GID,
 
686
                        DRM_DEV_MODE,
 
687
                        "dri/card%d", unit );
 
688
#elif defined(__NetBSD__)
 
689
        unit = minor(dev->device.dv_unit);
 
690
#endif
 
691
        DRM_SPININIT(dev->count_lock, "drm device");
 
692
        lockinit(&dev->dev_lock, PZERO, "drmlk", 0, 0);
 
693
        dev->name = DRIVER_NAME;
 
694
        DRM(mem_init)();
 
695
        DRM(sysctl_init)(dev);
 
696
        TAILQ_INIT(&dev->files);
 
697
 
 
698
#if __REALLY_HAVE_AGP
 
699
        dev->agp = DRM(agp_init)();
 
700
#if __MUST_HAVE_AGP
 
701
        if ( dev->agp == NULL ) {
 
702
                DRM_ERROR( "Cannot initialize the agpgart module.\n" );
 
703
                DRM(sysctl_cleanup)( dev );
 
704
#ifdef __FreeBSD__
 
705
                destroy_dev(dev->devnode);
 
706
#endif
 
707
                DRM(takedown)( dev );
 
708
                return DRM_ERR(ENOMEM);
 
709
        }
 
710
#endif /* __MUST_HAVE_AGP */
 
711
#if __REALLY_HAVE_MTRR
 
712
        if (dev->agp) {
 
713
#ifdef __FreeBSD__
 
714
                int retcode = 0, act;
 
715
                struct mem_range_desc mrdesc;
 
716
                mrdesc.mr_base = dev->agp->info.ai_aperture_base;
 
717
                mrdesc.mr_len = dev->agp->info.ai_aperture_size;
 
718
                mrdesc.mr_flags = MDF_WRITECOMBINE;
 
719
                act = MEMRANGE_SET_UPDATE;
 
720
                bcopy(DRIVER_NAME, &mrdesc.mr_owner, strlen(DRIVER_NAME));
 
721
                retcode = mem_range_attr_set(&mrdesc, &act);
 
722
                dev->agp->agp_mtrr=1;
 
723
#elif defined __NetBSD__
 
724
                struct mtrr mtrrmap;
 
725
                int one = 1;
 
726
                mtrrmap.base = dev->agp->info.ai_aperture_base;
 
727
                /* Might need a multiplier here XXX */
 
728
                mtrrmap.len = dev->agp->info.ai_aperture_size;
 
729
                mtrrmap.type = MTRR_TYPE_WC;
 
730
                mtrrmap.flags = MTRR_VALID;
 
731
                dev->agp->agp_mtrr = mtrr_set( &mtrrmap, &one, NULL, MTRR_GETSET_KERNEL);
 
732
#endif /* __NetBSD__ */
 
733
        }
 
734
#endif /* __REALLY_HAVE_MTRR */
 
735
#endif /* __REALLY_HAVE_AGP */
 
736
 
 
737
#if __HAVE_CTX_BITMAP
 
738
        retcode = DRM(ctxbitmap_init)( dev );
 
739
        if( retcode ) {
 
740
                DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
 
741
                DRM(sysctl_cleanup)( dev );
 
742
#ifdef __FreeBSD__
 
743
                destroy_dev(dev->devnode);
 
744
#endif
 
745
                DRM(takedown)( dev );
 
746
                return retcode;
 
747
        }
 
748
#endif
 
749
        DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
 
750
                DRIVER_NAME,
 
751
                DRIVER_MAJOR,
 
752
                DRIVER_MINOR,
 
753
                DRIVER_PATCHLEVEL,
 
754
                DRIVER_DATE,
 
755
                unit );
 
756
 
 
757
        DRIVER_POSTINIT();
 
758
 
 
759
        return 0;
 
760
}
 
761
 
 
762
/* linux: drm_cleanup is called via cleanup_module at module unload time.
 
763
 * bsd:   drm_cleanup is called per device at module unload time.
 
764
 * FIXME: NetBSD
 
765
 */
 
766
#ifdef __FreeBSD__
 
767
static void DRM(cleanup)(device_t nbdev)
 
768
#elif defined(__NetBSD__)
 
769
static void DRM(cleanup)(drm_device_t *dev)
 
770
#endif
 
771
{
 
772
#ifdef __FreeBSD__
 
773
        drm_device_t *dev;
 
774
#endif
 
775
#if __REALLY_HAVE_MTRR
 
776
#ifdef __NetBSD__
 
777
        struct mtrr mtrrmap;
 
778
        int one = 1;
 
779
#endif /* __NetBSD__ */
 
780
#endif /* __REALLY_HAVE_MTRR */
 
781
 
 
782
        DRM_DEBUG( "\n" );
 
783
 
 
784
#ifdef __FreeBSD__
 
785
        dev = device_get_softc(nbdev);
 
786
#endif
 
787
        DRM(sysctl_cleanup)( dev );
 
788
#ifdef __FreeBSD__
 
789
        destroy_dev(dev->devnode);
 
790
#endif
 
791
#if __HAVE_CTX_BITMAP
 
792
        DRM(ctxbitmap_cleanup)( dev );
 
793
#endif
 
794
 
 
795
#if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
 
796
        if ( dev->agp && dev->agp->agp_mtrr >= 0) {
 
797
#if defined(__NetBSD__)
 
798
                mtrrmap.base = dev->agp->info.ai_aperture_base;
 
799
                mtrrmap.len = dev->agp->info.ai_aperture_size;
 
800
                mtrrmap.type = 0;
 
801
                mtrrmap.flags = 0;
 
802
                retval = mtrr_set( &mtrrmap, &one, NULL, MTRR_GETSET_KERNEL);
 
803
#endif
 
804
        }
 
805
#endif
 
806
 
 
807
        DRM(takedown)( dev );
 
808
 
 
809
#if __REALLY_HAVE_AGP
 
810
        if ( dev->agp ) {
 
811
                DRM(agp_uninit)();
 
812
                DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
 
813
                dev->agp = NULL;
 
814
        }
 
815
#endif
 
816
        DRIVER_POSTCLEANUP();
 
817
        DRM(mem_uninit)();
 
818
        DRM_SPINUNINIT(dev->count_lock);
 
819
}
 
820
 
 
821
 
 
822
int DRM(version)( DRM_IOCTL_ARGS )
 
823
{
 
824
        drm_version_t version;
 
825
        int len;
 
826
 
 
827
        DRM_COPY_FROM_USER_IOCTL( version, (drm_version_t *)data, sizeof(version) );
 
828
 
 
829
#define DRM_COPY( name, value )                                         \
 
830
        len = strlen( value );                                          \
 
831
        if ( len > name##_len ) len = name##_len;                       \
 
832
        name##_len = strlen( value );                                   \
 
833
        if ( len && name ) {                                            \
 
834
                if ( DRM_COPY_TO_USER( name, value, len ) )             \
 
835
                        return DRM_ERR(EFAULT);                         \
 
836
        }
 
837
 
 
838
        version.version_major = DRIVER_MAJOR;
 
839
        version.version_minor = DRIVER_MINOR;
 
840
        version.version_patchlevel = DRIVER_PATCHLEVEL;
 
841
 
 
842
        DRM_COPY( version.name, DRIVER_NAME );
 
843
        DRM_COPY( version.date, DRIVER_DATE );
 
844
        DRM_COPY( version.desc, DRIVER_DESC );
 
845
 
 
846
        DRM_COPY_TO_USER_IOCTL( (drm_version_t *)data, version, sizeof(version) );
 
847
 
 
848
        return 0;
 
849
}
 
850
 
 
851
int DRM(open)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
 
852
{
 
853
        drm_device_t *dev = NULL;
 
854
        int retcode = 0;
 
855
 
 
856
        dev = DRIVER_SOFTC(minor(kdev));
 
857
 
 
858
        DRM_DEBUG( "open_count = %d\n", dev->open_count );
 
859
 
 
860
        retcode = DRM(open_helper)(kdev, flags, fmt, p, dev);
 
861
 
 
862
        if ( !retcode ) {
 
863
                atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
 
864
                DRM_SPINLOCK( &dev->count_lock );
 
865
#ifdef __FreeBSD__
 
866
                device_busy(dev->device);
 
867
#endif
 
868
                if ( !dev->open_count++ )
 
869
                        retcode = DRM(setup)( dev );
 
870
                DRM_SPINUNLOCK( &dev->count_lock );
 
871
        }
 
872
 
 
873
        return retcode;
 
874
}
 
875
 
 
876
int DRM(close)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p)
 
877
{
 
878
        drm_file_t *priv;
 
879
        DRM_DEVICE;
 
880
        int retcode = 0;
 
881
 
 
882
        DRM_DEBUG( "open_count = %d\n", dev->open_count );
 
883
        priv = DRM(find_file_by_proc)(dev, p);
 
884
        if (!priv) {
 
885
                DRM_DEBUG("can't find authenticator\n");
 
886
                return EINVAL;
 
887
        }
 
888
 
 
889
        DRIVER_PRERELEASE();
 
890
 
 
891
        /* ========================================================
 
892
         * Begin inline drm_release
 
893
         */
 
894
 
 
895
#ifdef __FreeBSD__
 
896
        DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
 
897
                   DRM_CURRENTPID, (long)dev->device, dev->open_count );
 
898
#elif defined(__NetBSD__)
 
899
        DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
 
900
                   DRM_CURRENTPID, (long)&dev->device, dev->open_count);
 
901
#endif
 
902
 
 
903
        if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
 
904
            && dev->lock.pid == DRM_CURRENTPID) {
 
905
                DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
 
906
                          DRM_CURRENTPID,
 
907
                          _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
 
908
#if HAVE_DRIVER_RELEASE
 
909
                DRIVER_RELEASE();
 
910
#endif
 
911
                DRM(lock_free)(dev,
 
912
                              &dev->lock.hw_lock->lock,
 
913
                              _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
 
914
                
 
915
                                /* FIXME: may require heavy-handed reset of
 
916
                                   hardware at this point, possibly
 
917
                                   processed via a callback to the X
 
918
                                   server. */
 
919
        }
 
920
#if __HAVE_RELEASE
 
921
        else if ( dev->lock.hw_lock ) {
 
922
                /* The lock is required to reclaim buffers */
 
923
                for (;;) {
 
924
                        if ( !dev->lock.hw_lock ) {
 
925
                                /* Device has been unregistered */
 
926
                                retcode = DRM_ERR(EINTR);
 
927
                                break;
 
928
                        }
 
929
                        if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
 
930
                                             DRM_KERNEL_CONTEXT ) ) {
 
931
                                dev->lock.pid       = p->p_pid;
 
932
                                dev->lock.lock_time = jiffies;
 
933
                                atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
 
934
                                break;  /* Got lock */
 
935
                        }
 
936
                                /* Contention */
 
937
#if 0
 
938
                        atomic_inc( &dev->total_sleeps );
 
939
#endif
 
940
                        retcode = tsleep(&dev->lock.lock_queue,
 
941
                                        PZERO|PCATCH,
 
942
                                        "drmlk2",
 
943
                                        0);
 
944
                        if (retcode)
 
945
                                break;
 
946
                }
 
947
                if( !retcode ) {
 
948
                        DRIVER_RELEASE();
 
949
                        DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
 
950
                                        DRM_KERNEL_CONTEXT );
 
951
                }
 
952
        }
 
953
#elif __HAVE_DMA
 
954
        DRM(reclaim_buffers)( dev, priv->pid );
 
955
#endif
 
956
 
 
957
#if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
 
958
        funsetown(&dev->buf_sigio);
 
959
#elif defined(__FreeBSD__)
 
960
        funsetown(dev->buf_sigio);
 
961
#elif defined(__NetBSD__)
 
962
        dev->buf_pgid = 0;
 
963
#endif /* __NetBSD__ */
 
964
 
 
965
        DRM_LOCK;
 
966
        priv = DRM(find_file_by_proc)(dev, p);
 
967
        if (priv) {
 
968
                priv->refs--;
 
969
                if (!priv->refs) {
 
970
                        TAILQ_REMOVE(&dev->files, priv, link);
 
971
                        DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
 
972
                }
 
973
        }
 
974
        DRM_UNLOCK;
 
975
 
 
976
 
 
977
        /* ========================================================
 
978
         * End inline drm_release
 
979
         */
 
980
 
 
981
        atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
 
982
        DRM_SPINLOCK( &dev->count_lock );
 
983
#ifdef __FreeBSD__
 
984
        device_unbusy(dev->device);
 
985
#endif
 
986
        if ( !--dev->open_count ) {
 
987
                if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
 
988
                        DRM_ERROR( "Device busy: %ld %d\n",
 
989
                                (unsigned long)atomic_read( &dev->ioctl_count ),
 
990
                                   dev->blocked );
 
991
                        DRM_SPINUNLOCK( &dev->count_lock );
 
992
                        return DRM_ERR(EBUSY);
 
993
                }
 
994
                DRM_SPINUNLOCK( &dev->count_lock );
 
995
                return DRM(takedown)( dev );
 
996
        }
 
997
        DRM_SPINUNLOCK( &dev->count_lock );
 
998
        
 
999
        return retcode;
 
1000
}
 
1001
 
 
1002
/* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
 
1003
 */
 
1004
int DRM(ioctl)( DRM_IOCTL_ARGS )
 
1005
{
 
1006
        DRM_DEVICE;
 
1007
        int retcode = 0;
 
1008
        drm_ioctl_desc_t *ioctl;
 
1009
        d_ioctl_t *func;
 
1010
        int nr = DRM_IOCTL_NR(cmd);
 
1011
        DRM_PRIV;
 
1012
 
 
1013
        atomic_inc( &dev->ioctl_count );
 
1014
        atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
 
1015
        ++priv->ioctl_count;
 
1016
 
 
1017
#ifdef __FreeBSD__
 
1018
        DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
 
1019
                 DRM_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated );
 
1020
#elif defined(__NetBSD__)
 
1021
        DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
 
1022
                 DRM_CURRENTPID, cmd, nr, (long)&dev->device, priv->authenticated );
 
1023
#endif
 
1024
 
 
1025
        switch (cmd) {
 
1026
        case FIONBIO:
 
1027
                atomic_dec(&dev->ioctl_count);
 
1028
                return 0;
 
1029
 
 
1030
        case FIOASYNC:
 
1031
                atomic_dec(&dev->ioctl_count);
 
1032
                dev->flags |= FASYNC;
 
1033
                return 0;
 
1034
 
 
1035
#ifdef __FreeBSD__
 
1036
        case FIOSETOWN:
 
1037
                atomic_dec(&dev->ioctl_count);
 
1038
                return fsetown(*(int *)data, &dev->buf_sigio);
 
1039
 
 
1040
        case FIOGETOWN:
 
1041
                atomic_dec(&dev->ioctl_count);
 
1042
#if (__FreeBSD_version >= 500000)
 
1043
                *(int *) data = fgetown(&dev->buf_sigio);
 
1044
#else
 
1045
                *(int *) data = fgetown(dev->buf_sigio);
 
1046
#endif
 
1047
                return 0;
 
1048
        }
 
1049
#endif /* __FreeBSD__ */
 
1050
#ifdef __NetBSD__
 
1051
        case TIOCSPGRP:
 
1052
                atomic_dec(&dev->ioctl_count);
 
1053
                dev->buf_pgid = *(int *)data;
 
1054
                return 0;
 
1055
 
 
1056
        case TIOCGPGRP:
 
1057
                atomic_dec(&dev->ioctl_count);
 
1058
                *(int *)data = dev->buf_pgid;
 
1059
                return 0;
 
1060
#endif /* __NetBSD__ */
 
1061
 
 
1062
        if ( nr >= DRIVER_IOCTL_COUNT ) {
 
1063
                retcode = EINVAL;
 
1064
        } else {
 
1065
                ioctl = &DRM(ioctls)[nr];
 
1066
                func = ioctl->func;
 
1067
 
 
1068
                if ( !func ) {
 
1069
                        DRM_DEBUG( "no function\n" );
 
1070
                        retcode = EINVAL;
 
1071
                } else if ( ( ioctl->root_only && DRM_SUSER(p) ) 
 
1072
                         || ( ioctl->auth_needed && !priv->authenticated ) ) {
 
1073
                        retcode = EACCES;
 
1074
                } else {
 
1075
                        retcode = func( kdev, cmd, data, flags, p );
 
1076
                }
 
1077
        }
 
1078
 
 
1079
        atomic_dec( &dev->ioctl_count );
 
1080
        return DRM_ERR(retcode);
 
1081
}
 
1082
 
 
1083
int DRM(lock)( DRM_IOCTL_ARGS )
 
1084
{
 
1085
        DRM_DEVICE;
 
1086
        drm_lock_t lock;
 
1087
        int ret = 0;
 
1088
#if __HAVE_MULTIPLE_DMA_QUEUES
 
1089
        drm_queue_t *q;
 
1090
#endif
 
1091
#if __HAVE_DMA_HISTOGRAM
 
1092
        cycles_t start;
 
1093
 
 
1094
        dev->lck_start = start = get_cycles();
 
1095
#endif
 
1096
 
 
1097
        DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) );
 
1098
 
 
1099
        if ( lock.context == DRM_KERNEL_CONTEXT ) {
 
1100
                DRM_ERROR( "Process %d using kernel context %d\n",
 
1101
                           DRM_CURRENTPID, lock.context );
 
1102
                return DRM_ERR(EINVAL);
 
1103
        }
 
1104
 
 
1105
        DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
 
1106
                   lock.context, DRM_CURRENTPID,
 
1107
                   dev->lock.hw_lock->lock, lock.flags );
 
1108
 
 
1109
#if __HAVE_DMA_QUEUE
 
1110
        if ( lock.context < 0 )
 
1111
                return DRM_ERR(EINVAL);
 
1112
#elif __HAVE_MULTIPLE_DMA_QUEUES
 
1113
        if ( lock.context < 0 || lock.context >= dev->queue_count )
 
1114
                return DRM_ERR(EINVAL);
 
1115
        q = dev->queuelist[lock.context];
 
1116
#endif
 
1117
 
 
1118
#if __HAVE_DMA_FLUSH
 
1119
        ret = DRM(flush_block_and_flush)( dev, lock.context, lock.flags );
 
1120
#endif
 
1121
        if ( !ret ) {
 
1122
                for (;;) {
 
1123
                        if ( !dev->lock.hw_lock ) {
 
1124
                                /* Device has been unregistered */
 
1125
                                ret = EINTR;
 
1126
                                break;
 
1127
                        }
 
1128
                        if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
 
1129
                                             lock.context ) ) {
 
1130
                                dev->lock.pid       = DRM_CURRENTPID;
 
1131
                                dev->lock.lock_time = jiffies;
 
1132
                                atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
 
1133
                                break;  /* Got lock */
 
1134
                        }
 
1135
 
 
1136
                                /* Contention */
 
1137
                        ret = tsleep((void *)&dev->lock.lock_queue,
 
1138
                                        PZERO|PCATCH,
 
1139
                                        "drmlk2",
 
1140
                                        0);
 
1141
                        if (ret)
 
1142
                                break;
 
1143
                }
 
1144
        }
 
1145
 
 
1146
#if __HAVE_DMA_FLUSH
 
1147
        DRM(flush_unblock)( dev, lock.context, lock.flags ); /* cleanup phase */
 
1148
#endif
 
1149
 
 
1150
        if ( !ret ) {
 
1151
 
 
1152
#if __HAVE_DMA_READY
 
1153
                if ( lock.flags & _DRM_LOCK_READY ) {
 
1154
                        DRIVER_DMA_READY();
 
1155
                }
 
1156
#endif
 
1157
#if __HAVE_DMA_QUIESCENT
 
1158
                if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
 
1159
                        DRIVER_DMA_QUIESCENT();
 
1160
                }
 
1161
#endif
 
1162
#if __HAVE_KERNEL_CTX_SWITCH
 
1163
                if ( dev->last_context != lock.context ) {
 
1164
                        DRM(context_switch)(dev, dev->last_context,
 
1165
                                            lock.context);
 
1166
                }
 
1167
#endif
 
1168
        }
 
1169
 
 
1170
        DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
 
1171
 
 
1172
#if __HAVE_DMA_HISTOGRAM
 
1173
        atomic_inc(&dev->histo.lacq[DRM(histogram_slot)(get_cycles()-start)]);
 
1174
#endif
 
1175
 
 
1176
        return DRM_ERR(ret);
 
1177
}
 
1178
 
 
1179
 
 
1180
int DRM(unlock)( DRM_IOCTL_ARGS )
 
1181
{
 
1182
        DRM_DEVICE;
 
1183
        drm_lock_t lock;
 
1184
 
 
1185
        DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) ) ;
 
1186
 
 
1187
        if ( lock.context == DRM_KERNEL_CONTEXT ) {
 
1188
                DRM_ERROR( "Process %d using kernel context %d\n",
 
1189
                           DRM_CURRENTPID, lock.context );
 
1190
                return DRM_ERR(EINVAL);
 
1191
        }
 
1192
 
 
1193
        atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
 
1194
 
 
1195
#if __HAVE_KERNEL_CTX_SWITCH
 
1196
        /* We no longer really hold it, but if we are the next
 
1197
         * agent to request it then we should just be able to
 
1198
         * take it immediately and not eat the ioctl.
 
1199
         */
 
1200
        dev->lock.pid = 0;
 
1201
        {
 
1202
                __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
 
1203
                unsigned int old, new, prev, ctx;
 
1204
 
 
1205
                ctx = lock.context;
 
1206
                do {
 
1207
                        old  = *plock;
 
1208
                        new  = ctx;
 
1209
                        prev = cmpxchg(plock, old, new);
 
1210
                } while (prev != old);
 
1211
        }
 
1212
        wake_up_interruptible(&dev->lock.lock_queue);
 
1213
#else
 
1214
        DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
 
1215
                            DRM_KERNEL_CONTEXT );
 
1216
#if __HAVE_DMA_SCHEDULE
 
1217
        DRM(dma_schedule)( dev, 1 );
 
1218
#endif
 
1219
 
 
1220
        /* FIXME: Do we ever really need to check this?
 
1221
         */
 
1222
        if ( 1 /* !dev->context_flag */ ) {
 
1223
                if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
 
1224
                                     DRM_KERNEL_CONTEXT ) ) {
 
1225
                        DRM_ERROR( "\n" );
 
1226
                }
 
1227
        }
 
1228
#endif /* !__HAVE_KERNEL_CTX_SWITCH */
 
1229
 
 
1230
        return 0;
 
1231
}
 
1232
 
 
1233
#if DRM_LINUX
 
1234
#define LINUX_IOCTL_DRM_MIN             0x6400
 
1235
#define LINUX_IOCTL_DRM_MAX             0x64ff
 
1236
 
 
1237
static linux_ioctl_function_t DRM( linux_ioctl);
 
1238
static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
 
1239
SYSINIT  (DRM( register),   SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler));
 
1240
SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler));
 
1241
 
 
1242
#define LINUX_IOC_VOID  IOC_VOID
 
1243
#define LINUX_IOC_IN    IOC_OUT         /* Linux has the values the other way around */
 
1244
#define LINUX_IOC_OUT   IOC_IN
 
1245
 
 
1246
/*
 
1247
 * Linux emulation IOCTL
 
1248
 */
 
1249
static int
 
1250
DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
 
1251
{
 
1252
        u_long          cmd = args->cmd;
 
1253
#define STK_PARAMS      128
 
1254
        union {
 
1255
            char stkbuf[STK_PARAMS];
 
1256
            long align;
 
1257
        } ubuf;
 
1258
        caddr_t         data=NULL, memp=NULL;
 
1259
        u_int           size = IOCPARM_LEN(cmd);
 
1260
        int             error;
 
1261
#if (__FreeBSD_version >= 500000)
 
1262
        struct file     *fp;
 
1263
#else
 
1264
        struct file     *fp = p->p_fd->fd_ofiles[args->fd];
 
1265
#endif
 
1266
        if ( size > STK_PARAMS ) {
 
1267
                if ( size > IOCPARM_MAX )
 
1268
                        return EINVAL;
 
1269
                memp = malloc( (u_long)size, DRM(M_DRM), M_WAITOK );
 
1270
                data = memp;
 
1271
        } else {
 
1272
                data = ubuf.stkbuf;
 
1273
        }
 
1274
 
 
1275
        if ( cmd & LINUX_IOC_IN ) {
 
1276
                if ( size ) {
 
1277
                        error = copyin( (caddr_t)args->arg, data, (u_int)size );
 
1278
                        if (error) {
 
1279
                                if ( memp )
 
1280
                                        free( data, DRM(M_DRM) );
 
1281
                                return error;
 
1282
                        }
 
1283
                } else {
 
1284
                        data = (caddr_t)args->arg;
 
1285
                }
 
1286
        } else if ( (cmd & LINUX_IOC_OUT) && size ) {
 
1287
                /*
 
1288
                 * Zero the buffer so the user always
 
1289
                 * gets back something deterministic.
 
1290
                 */
 
1291
                bzero( data, size );
 
1292
        } else if ( cmd & LINUX_IOC_VOID ) {
 
1293
                *(caddr_t *)data = (caddr_t)args->arg;
 
1294
        }
 
1295
 
 
1296
#if (__FreeBSD_version >= 500000)
 
1297
        if ( (error = fget( p, args->fd, &fp )) != 0 ) {
 
1298
                if ( memp )
 
1299
                        free( memp, DRM(M_DRM) );
 
1300
                return (error);
 
1301
        }
 
1302
        error = fo_ioctl( fp, cmd, data, p->td_ucred, p );
 
1303
        fdrop( fp, p );
 
1304
#else
 
1305
        error = fo_ioctl( fp, cmd, data, p );
 
1306
#endif
 
1307
        if ( error == 0 && (cmd & LINUX_IOC_OUT) && size )
 
1308
                error = copyout( data, (caddr_t)args->arg, (u_int)size );
 
1309
        if ( memp )
 
1310
                free( memp, DRM(M_DRM) );
 
1311
        return error;
 
1312
}
 
1313
#endif /* DRM_LINUX */