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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm/] [ffb_drv.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: ffb_drv.c,v 1.1.1.1 2004-04-15 02:01:23 phoenix Exp $
2
 * ffb_drv.c: Creator/Creator3D direct rendering driver.
3
 *
4
 * Copyright (C) 2000 David S. Miller (davem@redhat.com)
5
 */
6
 
7
#include <linux/config.h>
8
#include "ffb.h"
9
#include "drmP.h"
10
 
11
#include "ffb_drv.h"
12
 
13
#include <linux/sched.h>
14
#include <linux/smp_lock.h>
15
#include <asm/shmparam.h>
16
#include <asm/oplib.h>
17
#include <asm/upa.h>
18
 
19
#define DRIVER_AUTHOR           "David S. Miller"
20
 
21
#define DRIVER_NAME             "ffb"
22
#define DRIVER_DESC             "Creator/Creator3D"
23
#define DRIVER_DATE             "20000517"
24
 
25
#define DRIVER_MAJOR            0
26
#define DRIVER_MINOR            0
27
#define DRIVER_PATCHLEVEL       1
28
 
29
#define DRIVER_FOPS                                             \
30
static struct file_operations   DRM(fops) = {                   \
31
        owner:                  THIS_MODULE,                    \
32
        open:                   DRM(open),                      \
33
        flush:                  DRM(flush),                     \
34
        release:                DRM(release),                   \
35
        ioctl:                  DRM(ioctl),                     \
36
        mmap:                   DRM(mmap),                      \
37
        read:                   DRM(read),                      \
38
        fasync:                 DRM(fasync),                    \
39
        poll:                   DRM(poll),                      \
40
        get_unmapped_area:      ffb_get_unmapped_area,          \
41
}
42
 
43
#define DRIVER_COUNT_CARDS()    ffb_count_card_instances()
44
/* Allocate private structure and fill it */
45
#define DRIVER_PRESETUP()       do {            \
46
        int _ret;                               \
47
        _ret = ffb_presetup(dev);               \
48
        if (_ret != 0) return _ret;              \
49
} while(0)
50
 
51
/* Free private structure */
52
#define DRIVER_PRETAKEDOWN()    do {                            \
53
        if (dev->dev_private) kfree(dev->dev_private);          \
54
} while(0)
55
 
56
#define DRIVER_POSTCLEANUP()    do {                            \
57
        if (ffb_position != NULL) kfree(ffb_position);          \
58
} while(0)
59
 
60
/* We have to free up the rogue hw context state holding error or
61
 * else we will leak it.
62
 */
63
#define DRIVER_RELEASE()        do {                                    \
64
        ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;    \
65
        int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);    \
66
        int idx;                                                        \
67
                                                                        \
68
        idx = context - 1;                                              \
69
        if (fpriv &&                                                    \
70
            context != DRM_KERNEL_CONTEXT &&                            \
71
            fpriv->hw_state[idx] != NULL) {                             \
72
                kfree(fpriv->hw_state[idx]);                            \
73
                fpriv->hw_state[idx] = NULL;                            \
74
        }                                                               \
75
} while(0)
76
 
77
/* For mmap customization */
78
#define DRIVER_GET_MAP_OFS()    (map->offset & 0xffffffff)
79
#define DRIVER_GET_REG_OFS()    ffb_get_reg_offset(dev)
80
 
81
typedef struct _ffb_position_t {
82
        int node;
83
        int root;
84
} ffb_position_t;
85
 
86
static ffb_position_t *ffb_position;
87
 
88
static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
89
{
90
        volatile unsigned char *strap_bits;
91
        unsigned char val;
92
 
93
        strap_bits = (volatile unsigned char *)
94
                (ffb_priv->card_phys_base + 0x00200000UL);
95
 
96
        /* Don't ask, you have to read the value twice for whatever
97
         * reason to get correct contents.
98
         */
99
        val = upa_readb(strap_bits);
100
        val = upa_readb(strap_bits);
101
        switch (val & 0x78) {
102
        case (0x0 << 5) | (0x0 << 3):
103
                ffb_priv->ffb_type = ffb1_prototype;
104
                printk("ffb%d: Detected FFB1 pre-FCS prototype\n", instance);
105
                break;
106
        case (0x0 << 5) | (0x1 << 3):
107
                ffb_priv->ffb_type = ffb1_standard;
108
                printk("ffb%d: Detected FFB1\n", instance);
109
                break;
110
        case (0x0 << 5) | (0x3 << 3):
111
                ffb_priv->ffb_type = ffb1_speedsort;
112
                printk("ffb%d: Detected FFB1-SpeedSort\n", instance);
113
                break;
114
        case (0x1 << 5) | (0x0 << 3):
115
                ffb_priv->ffb_type = ffb2_prototype;
116
                printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n", instance);
117
                break;
118
        case (0x1 << 5) | (0x1 << 3):
119
                ffb_priv->ffb_type = ffb2_vertical;
120
                printk("ffb%d: Detected FFB2/vertical\n", instance);
121
                break;
122
        case (0x1 << 5) | (0x2 << 3):
123
                ffb_priv->ffb_type = ffb2_vertical_plus;
124
                printk("ffb%d: Detected FFB2+/vertical\n", instance);
125
                break;
126
        case (0x2 << 5) | (0x0 << 3):
127
                ffb_priv->ffb_type = ffb2_horizontal;
128
                printk("ffb%d: Detected FFB2/horizontal\n", instance);
129
                break;
130
        case (0x2 << 5) | (0x2 << 3):
131
                ffb_priv->ffb_type = ffb2_horizontal;
132
                printk("ffb%d: Detected FFB2+/horizontal\n", instance);
133
                break;
134
        default:
135
                ffb_priv->ffb_type = ffb2_vertical;
136
                printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n", instance, val);
137
                break;
138
        };
139
}
140
 
141
static void ffb_apply_upa_parent_ranges(int parent,
142
                                        struct linux_prom64_registers *regs)
143
{
144
        struct linux_prom64_ranges ranges[PROMREG_MAX];
145
        char name[128];
146
        int len, i;
147
 
148
        prom_getproperty(parent, "name", name, sizeof(name));
149
        if (strcmp(name, "upa") != 0)
150
                return;
151
 
152
        len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
153
        if (len <= 0)
154
                return;
155
 
156
        len /= sizeof(struct linux_prom64_ranges);
157
        for (i = 0; i < len; i++) {
158
                struct linux_prom64_ranges *rng = &ranges[i];
159
                u64 phys_addr = regs->phys_addr;
160
 
161
                if (phys_addr >= rng->ot_child_base &&
162
                    phys_addr < (rng->ot_child_base + rng->or_size)) {
163
                        regs->phys_addr -= rng->ot_child_base;
164
                        regs->phys_addr += rng->ot_parent_base;
165
                        return;
166
                }
167
        }
168
 
169
        return;
170
}
171
 
172
static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
173
                        int instance)
174
{
175
        struct linux_prom64_registers regs[2*PROMREG_MAX];
176
        ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
177
        int i;
178
 
179
        ffb_priv->prom_node = prom_node;
180
        if (prom_getproperty(ffb_priv->prom_node, "reg",
181
                             (void *)regs, sizeof(regs)) <= 0) {
182
                return -EINVAL;
183
        }
184
        ffb_apply_upa_parent_ranges(parent_node, &regs[0]);
185
        ffb_priv->card_phys_base = regs[0].phys_addr;
186
        ffb_priv->regs = (ffb_fbcPtr)
187
                (regs[0].phys_addr + 0x00600000UL);
188
        get_ffb_type(ffb_priv, instance);
189
        for (i = 0; i < FFB_MAX_CTXS; i++)
190
                ffb_priv->hw_state[i] = NULL;
191
 
192
        return 0;
193
}
194
 
195
static int __init ffb_count_siblings(int root)
196
{
197
        int node, child, count = 0;
198
 
199
        child = prom_getchild(root);
200
        for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
201
             node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
202
                count++;
203
 
204
        return count;
205
}
206
 
207
static int __init ffb_scan_siblings(int root, int instance)
208
{
209
        int node, child;
210
 
211
        child = prom_getchild(root);
212
        for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
213
             node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) {
214
                ffb_position[instance].node = node;
215
                ffb_position[instance].root = root;
216
                instance++;
217
        }
218
 
219
        return instance;
220
}
221
 
222
static int ffb_presetup(drm_device_t *);
223
 
224
static int __init ffb_count_card_instances(void)
225
{
226
        int root, total, instance;
227
 
228
        total = ffb_count_siblings(prom_root_node);
229
        root = prom_getchild(prom_root_node);
230
        for (root = prom_searchsiblings(root, "upa"); root;
231
             root = prom_searchsiblings(prom_getsibling(root), "upa"))
232
                total += ffb_count_siblings(root);
233
 
234
        ffb_position = kmalloc(sizeof(ffb_position_t) * total, GFP_KERNEL);
235
 
236
        /* Actual failure will be caught during ffb_presetup b/c we can't catch
237
         * it easily here.
238
         */
239
        if (!ffb_position)
240
                return -ENOMEM;
241
 
242
        instance = ffb_scan_siblings(prom_root_node, 0);
243
 
244
        root = prom_getchild(prom_root_node);
245
        for (root = prom_searchsiblings(root, "upa"); root;
246
             root = prom_searchsiblings(prom_getsibling(root), "upa"))
247
                instance = ffb_scan_siblings(root, instance);
248
 
249
        return total;
250
}
251
 
252
static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
253
{
254
        drm_file_t      *priv   = filp->private_data;
255
        drm_device_t    *dev;
256
        drm_map_list_t  *r_list;
257
        struct list_head *list;
258
        drm_map_t       *map;
259
 
260
        if (!priv || (dev = priv->dev) == NULL)
261
                return NULL;
262
 
263
        list_for_each(list, &dev->maplist->head) {
264
                unsigned long uoff;
265
 
266
                r_list = (drm_map_list_t *)list;
267
                map = r_list->map;
268
                if (!map)
269
                        continue;
270
                uoff = (map->offset & 0xffffffff);
271
                if (uoff == off)
272
                        return map;
273
        }
274
 
275
        return NULL;
276
}
277
 
278
static unsigned long ffb_get_unmapped_area(struct file *filp,
279
                                           unsigned long hint,
280
                                           unsigned long len,
281
                                           unsigned long pgoff,
282
                                           unsigned long flags)
283
{
284
        drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
285
        unsigned long addr = -ENOMEM;
286
 
287
        if (!map)
288
                return get_unmapped_area(NULL, hint, len, pgoff, flags);
289
 
290
        if (map->type == _DRM_FRAME_BUFFER ||
291
            map->type == _DRM_REGISTERS) {
292
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
293
                addr = get_fb_unmapped_area(filp, hint, len, pgoff, flags);
294
#else
295
                addr = get_unmapped_area(NULL, hint, len, pgoff, flags);
296
#endif
297
        } else if (map->type == _DRM_SHM && SHMLBA > PAGE_SIZE) {
298
                unsigned long slack = SHMLBA - PAGE_SIZE;
299
 
300
                addr = get_unmapped_area(NULL, hint, len + slack, pgoff, flags);
301
                if (!(addr & ~PAGE_MASK)) {
302
                        unsigned long kvirt = (unsigned long) map->handle;
303
 
304
                        if ((kvirt & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
305
                                unsigned long koff, aoff;
306
 
307
                                koff = kvirt & (SHMLBA - 1);
308
                                aoff = addr & (SHMLBA - 1);
309
                                if (koff < aoff)
310
                                        koff += SHMLBA;
311
 
312
                                addr += (koff - aoff);
313
                        }
314
                }
315
        } else {
316
                addr = get_unmapped_area(NULL, hint, len, pgoff, flags);
317
        }
318
 
319
        return addr;
320
}
321
 
322
static unsigned long ffb_get_reg_offset(drm_device_t *dev)
323
{
324
        ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
325
 
326
        if (ffb_priv)
327
                return ffb_priv->card_phys_base;
328
 
329
        return 0;
330
}
331
 
332
#include "drm_auth.h"
333
#include "drm_bufs.h"
334
#include "drm_dma.h"
335
#include "drm_drawable.h"
336
#include "drm_drv.h"
337
 
338
/* This functions must be here since it references DRM(numdevs)
339
 * which drm_drv.h declares.
340
 */
341
static int ffb_presetup(drm_device_t *dev)
342
{
343
        ffb_dev_priv_t  *ffb_priv;
344
        drm_device_t *temp_dev;
345
        int ret = 0;
346
        int i;
347
 
348
        /* Check for the case where no device was found. */
349
        if (ffb_position == NULL)
350
                return -ENODEV;
351
 
352
        /* Find our instance number by finding our device in dev structure */
353
        for (i = 0; i < DRM(numdevs); i++) {
354
                temp_dev = &(DRM(device)[i]);
355
                if(temp_dev == dev)
356
                        break;
357
        }
358
 
359
        if (i == DRM(numdevs))
360
                return -ENODEV;
361
 
362
        ffb_priv = kmalloc(sizeof(ffb_dev_priv_t), GFP_KERNEL);
363
        if (!ffb_priv)
364
                return -ENOMEM;
365
        memset(ffb_priv, 0, sizeof(*ffb_priv));
366
        dev->dev_private = ffb_priv;
367
 
368
        ret = ffb_init_one(dev,
369
                           ffb_position[i].node,
370
                           ffb_position[i].root,
371
                           i);
372
        return ret;
373
}
374
 
375
#include "drm_fops.h"
376
#include "drm_init.h"
377
#include "drm_ioctl.h"
378
#include "drm_lock.h"
379
#include "drm_memory.h"
380
#include "drm_proc.h"
381
#include "drm_vm.h"
382
#include "drm_stub.h"

powered by: WebSVN 2.1.0

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