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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [nubus/] [nubus.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      Macintosh Nubus Interface Code
3
 *
4
 *      Originally by Alan Cox
5
 *
6
 *      Mostly rewritten by David Huggins-Daines, C. Scott Ananian,
7
 *      and others.
8
 */
9
 
10
#include <linux/config.h>
11
#include <linux/ptrace.h>
12
#include <linux/types.h>
13
#include <linux/kernel.h>
14
#include <linux/string.h>
15
#include <linux/nubus.h>
16
#include <linux/errno.h>
17
#include <linux/init.h>
18
#include <linux/delay.h>
19
#include <asm/setup.h>
20
#include <asm/system.h>
21
#include <asm/page.h>
22
#include <asm/hwtest.h>
23
#include <linux/proc_fs.h>
24
#include <asm/mac_via.h>
25
#include <asm/mac_oss.h>
26
 
27
extern void via_nubus_init(void);
28
extern void oss_nubus_init(void);
29
 
30
/* Constants */
31
 
32
/* This is, of course, the size in bytelanes, rather than the size in
33
   actual bytes */
34
#define FORMAT_BLOCK_SIZE 20
35
#define ROM_DIR_OFFSET 0x24
36
 
37
#define NUBUS_TEST_PATTERN 0x5A932BC7
38
 
39
/* Define this if you like to live dangerously - it is known not to
40
   work on pretty much every machine except the Quadra 630 and the LC
41
   III. */
42
#undef I_WANT_TO_PROBE_SLOT_ZERO
43
 
44
/* This sometimes helps combat failure to boot */
45
#undef TRY_TO_DODGE_WSOD
46
 
47
/* Globals */
48
 
49
struct nubus_dev*   nubus_devices;
50
struct nubus_board* nubus_boards;
51
 
52
/* Meaning of "bytelanes":
53
 
54
   The card ROM may appear on any or all bytes of each long word in
55
   NuBus memory.  The low 4 bits of the "map" value found in the
56
   format block (at the top of the slot address space, as well as at
57
   the top of the MacOS ROM) tells us which bytelanes, i.e. which byte
58
   offsets within each longword, are valid.  Thus:
59
 
60
   A map of 0x0f, as found in the MacOS ROM, means that all bytelanes
61
   are valid.
62
 
63
   A map of 0xf0 means that no bytelanes are valid (We pray that we
64
   will never encounter this, but stranger things have happened)
65
 
66
   A map of 0xe1 means that only the MSB of each long word is actually
67
   part of the card ROM.  (We hope to never encounter NuBus on a
68
   little-endian machine.  Again, stranger things have happened)
69
 
70
   A map of 0x78 means that only the LSB of each long word is valid.
71
 
72
   Etcetera, etcetera.  Hopefully this clears up some confusion over
73
   what the following code actually does.  */
74
 
75
static inline int not_useful(void *p, int map)
76
{
77
        unsigned long pv=(unsigned long)p;
78
        pv &= 3;
79
        if(map & (1<<pv))
80
                return 0;
81
        return 1;
82
}
83
 
84
static unsigned long nubus_get_rom(unsigned char **ptr, int len, int map)
85
{
86
        /* This will hold the result */
87
        unsigned long v = 0;
88
        unsigned char *p = *ptr;
89
 
90
        while(len)
91
        {
92
                v <<= 8;
93
                while(not_useful(p,map))
94
                        p++;
95
                v |= *p++;
96
                len--;
97
        }
98
        *ptr = p;
99
        return v;
100
}
101
 
102
static void nubus_rewind(unsigned char **ptr, int len, int map)
103
{
104
        unsigned char *p=*ptr;
105
 
106
        /* Sanity check */
107
        if(len > 65536)
108
                printk(KERN_ERR "rewind of 0x%08x!\n", len);
109
        while(len)
110
        {
111
                do
112
                {
113
                        p--;
114
                }
115
                while(not_useful(p, map));
116
                len--;
117
        }
118
        *ptr=p;
119
}
120
 
121
static void nubus_advance(unsigned char **ptr, int len, int map)
122
{
123
        unsigned char *p = *ptr;
124
        if(len>65536)
125
                printk(KERN_ERR "advance of 0x%08x!\n", len);
126
        while(len)
127
        {
128
                while(not_useful(p,map))
129
                        p++;
130
                        p++;
131
                len--;
132
        }
133
        *ptr = p;
134
}
135
 
136
static void nubus_move(unsigned char **ptr, int len, int map)
137
{
138
        if(len > 0)
139
                nubus_advance(ptr, len, map);
140
        else if(len < 0)
141
                nubus_rewind(ptr, -len, map);
142
}
143
 
144
/* Now, functions to read the sResource tree */
145
 
146
/* Each sResource entry consists of a 1-byte ID and a 3-byte data
147
   field.  If that data field contains an offset, then obviously we
148
   have to expand it from a 24-bit signed number to a 32-bit signed
149
   number. */
150
 
151
static inline long nubus_expand32(long foo)
152
{
153
        if(foo & 0x00800000)    /* 24bit negative */
154
                foo |= 0xFF000000;
155
        return foo;
156
}
157
 
158
static inline void *nubus_rom_addr(int slot)
159
{
160
        /*
161
         *      Returns the first byte after the card. We then walk
162
         *      backwards to get the lane register and the config
163
         */
164
        return (void *)(0xF1000000+(slot<<24));
165
}
166
 
167
static unsigned char *nubus_dirptr(const struct nubus_dirent *nd)
168
{
169
        unsigned char *p = nd->base;
170
        /* Essentially, just step over the bytelanes using whatever
171
           offset we might have found */
172
        nubus_move(&p, nubus_expand32(nd->data), nd->mask);
173
        /* And return the value */
174
        return p;
175
}
176
 
177
/* These two are for pulling resource data blocks (i.e. stuff that's
178
   pointed to with offsets) out of the card ROM. */
179
 
180
void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent* dirent,
181
                        int len)
182
{
183
        unsigned char *t = (unsigned char *)dest;
184
        unsigned char *p = nubus_dirptr(dirent);
185
        while(len)
186
        {
187
                *t++ = nubus_get_rom(&p, 1, dirent->mask);
188
                len--;
189
        }
190
}
191
 
192
void nubus_get_rsrc_str(void *dest, const struct nubus_dirent* dirent,
193
                        int len)
194
{
195
        unsigned char *t=(unsigned char *)dest;
196
        unsigned char *p = nubus_dirptr(dirent);
197
        while(len)
198
        {
199
                *t = nubus_get_rom(&p, 1, dirent->mask);
200
                if(!*t++)
201
                        break;
202
                len--;
203
        }
204
}
205
 
206
int nubus_get_root_dir(const struct nubus_board* board,
207
                       struct nubus_dir* dir)
208
{
209
        dir->ptr = dir->base = board->directory;
210
        dir->done = 0;
211
        dir->mask = board->lanes;
212
        return 0;
213
}
214
 
215
/* This is a slyly renamed version of the above */
216
int nubus_get_func_dir(const struct nubus_dev* dev,
217
                       struct nubus_dir* dir)
218
{
219
        dir->ptr = dir->base = dev->directory;
220
        dir->done = 0;
221
        dir->mask = dev->board->lanes;
222
        return 0;
223
}
224
 
225
int nubus_get_board_dir(const struct nubus_board* board,
226
                        struct nubus_dir* dir)
227
{
228
        struct nubus_dirent ent;
229
 
230
        dir->ptr = dir->base = board->directory;
231
        dir->done = 0;
232
        dir->mask = board->lanes;
233
 
234
        /* Now dereference it (the first directory is always the board
235
           directory) */
236
        if (nubus_readdir(dir, &ent) == -1)
237
                return -1;
238
        if (nubus_get_subdir(&ent, dir) == -1)
239
                return -1;
240
        return 0;
241
}
242
 
243
int nubus_get_subdir(const struct nubus_dirent *ent,
244
                     struct nubus_dir *dir)
245
{
246
        dir->ptr = dir->base = nubus_dirptr(ent);
247
        dir->done = 0;
248
        dir->mask = ent->mask;
249
        return 0;
250
}
251
 
252
int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
253
{
254
        u32 resid;
255
        if (nd->done)
256
                return -1;
257
 
258
        /* Do this first, otherwise nubus_rewind & co are off by 4 */
259
        ent->base = nd->ptr;
260
 
261
        /* This moves nd->ptr forward */
262
        resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
263
 
264
        /* EOL marker, as per the Apple docs */
265
        if((resid&0xff000000) == 0xff000000)
266
        {
267
                /* Mark it as done */
268
                nd->done = 1;
269
                return -1;
270
        }
271
 
272
        /* First byte is the resource ID */
273
        ent->type  = resid >> 24;
274
        /* Low 3 bytes might contain data (or might not) */
275
        ent->data = resid & 0xffffff;
276
        ent->mask  = nd->mask;
277
        return 0;
278
}
279
 
280
int nubus_rewinddir(struct nubus_dir* dir)
281
{
282
        dir->ptr = dir->base;
283
        return 0;
284
}
285
 
286
/* Driver interface functions, more or less like in pci.c */
287
 
288
struct nubus_dev*
289
nubus_find_device(unsigned short category,
290
                  unsigned short type,
291
                  unsigned short dr_hw,
292
                  unsigned short dr_sw,
293
                  const struct nubus_dev* from)
294
{
295
        struct nubus_dev* itor =
296
                from ? from->next : nubus_devices;
297
 
298
        while (itor) {
299
                if (itor->category == category
300
                    && itor->type == type
301
                    && itor->dr_hw == dr_hw
302
                    && itor->dr_sw == dr_sw)
303
                        return itor;
304
                itor = itor->next;
305
        }
306
        return NULL;
307
}
308
 
309
struct nubus_dev*
310
nubus_find_type(unsigned short category,
311
                unsigned short type,
312
                const struct nubus_dev* from)
313
{
314
        struct nubus_dev* itor =
315
                from ? from->next : nubus_devices;
316
 
317
        while (itor) {
318
                if (itor->category == category
319
                    && itor->type == type)
320
                        return itor;
321
                itor = itor->next;
322
        }
323
        return NULL;
324
}
325
 
326
struct nubus_dev*
327
nubus_find_slot(unsigned int slot,
328
                const struct nubus_dev* from)
329
{
330
        struct nubus_dev* itor =
331
                from ? from->next : nubus_devices;
332
 
333
        while (itor) {
334
                if (itor->board->slot == slot)
335
                        return itor;
336
                itor = itor->next;
337
        }
338
        return NULL;
339
}
340
 
341
int
342
nubus_find_rsrc(struct nubus_dir* dir, unsigned char rsrc_type,
343
                struct nubus_dirent* ent)
344
{
345
        while (nubus_readdir(dir, ent) != -1) {
346
                if (ent->type == rsrc_type)
347
                        return 0;
348
        }
349
        return -1;
350
}
351
 
352
/* Initialization functions - decide which slots contain stuff worth
353
   looking at, and print out lots and lots of information from the
354
   resource blocks. */
355
 
356
/* FIXME: A lot of this stuff will eventually be useful after
357
   initializaton, for intelligently probing Ethernet and video chips,
358
   among other things.  The rest of it should go in the /proc code.
359
   For now, we just use it to give verbose boot logs. */
360
 
361
static int __init nubus_show_display_resource(struct nubus_dev* dev,
362
                                              const struct nubus_dirent* ent)
363
{
364
        switch (ent->type) {
365
        case NUBUS_RESID_GAMMADIR:
366
                printk(KERN_INFO "    gamma directory offset: 0x%06x\n", ent->data);
367
                break;
368
        case 0x0080 ... 0x0085:
369
                printk(KERN_INFO "    mode %02X info offset: 0x%06x\n",
370
                       ent->type, ent->data);
371
                break;
372
        default:
373
                printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
374
                       ent->type, ent->data);
375
        }
376
        return 0;
377
}
378
 
379
static int __init nubus_show_network_resource(struct nubus_dev* dev,
380
                                              const struct nubus_dirent* ent)
381
{
382
        switch (ent->type) {
383
        case NUBUS_RESID_MAC_ADDRESS:
384
        {
385
                char addr[6];
386
                int i;
387
 
388
                nubus_get_rsrc_mem(addr, ent, 6);
389
                printk(KERN_INFO "    MAC address: ");
390
                for (i = 0; i < 6; i++)
391
                        printk("%02x%s", addr[i] & 0xff,
392
                               i == 5 ? "" : ":");
393
                printk("\n");
394
                break;
395
        }
396
        default:
397
                printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
398
                       ent->type, ent->data);
399
        }
400
        return 0;
401
}
402
 
403
static int __init nubus_show_cpu_resource(struct nubus_dev* dev,
404
                                          const struct nubus_dirent* ent)
405
{
406
        switch (ent->type) {
407
        case NUBUS_RESID_MEMINFO:
408
        {
409
                unsigned long meminfo[2];
410
                nubus_get_rsrc_mem(&meminfo, ent, 8);
411
                printk(KERN_INFO "    memory: [ 0x%08lx 0x%08lx ]\n",
412
                       meminfo[0], meminfo[1]);
413
                break;
414
        }
415
        case NUBUS_RESID_ROMINFO:
416
        {
417
                unsigned long rominfo[2];
418
                nubus_get_rsrc_mem(&rominfo, ent, 8);
419
                printk(KERN_INFO "    ROM:    [ 0x%08lx 0x%08lx ]\n",
420
                       rominfo[0], rominfo[1]);
421
                break;
422
        }
423
        default:
424
                printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
425
                       ent->type, ent->data);
426
        }
427
        return 0;
428
}
429
 
430
static int __init nubus_show_private_resource(struct nubus_dev* dev,
431
                                              const struct nubus_dirent* ent)
432
{
433
        switch (dev->category) {
434
        case NUBUS_CAT_DISPLAY:
435
                nubus_show_display_resource(dev, ent);
436
                break;
437
        case NUBUS_CAT_NETWORK:
438
                nubus_show_network_resource(dev, ent);
439
                break;
440
        case NUBUS_CAT_CPU:
441
                nubus_show_cpu_resource(dev, ent);
442
                break;
443
        default:
444
                printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
445
                       ent->type, ent->data);
446
        }
447
        return 0;
448
}
449
 
450
static struct nubus_dev* __init
451
           nubus_get_functional_resource(struct nubus_board* board,
452
                                         int slot,
453
                                         const struct nubus_dirent* parent)
454
{
455
        struct nubus_dir    dir;
456
        struct nubus_dirent ent;
457
        struct nubus_dev*   dev;
458
 
459
        printk(KERN_INFO "  Function 0x%02x:\n", parent->type);
460
        nubus_get_subdir(parent, &dir);
461
 
462
        /* Apple seems to have botched the ROM on the IIx */
463
        if (slot == 0 && (unsigned long)dir.base % 2)
464
                dir.base += 1;
465
 
466
        if (console_loglevel >= 10)
467
                printk(KERN_DEBUG "nubus_get_functional_resource: parent is 0x%p, dir is 0x%p\n",
468
                       parent->base, dir.base);
469
 
470
        /* Actually we should probably panic if this fails */
471
        if ((dev = kmalloc(sizeof(*dev), GFP_ATOMIC)) == NULL)
472
                return NULL;
473
        memset(dev, 0, sizeof(*dev));
474
        dev->resid = parent->type;
475
        dev->directory = dir.base;
476
        dev->board = board;
477
 
478
        while (nubus_readdir(&dir, &ent) != -1)
479
        {
480
                switch(ent.type)
481
                {
482
                case NUBUS_RESID_TYPE:
483
                {
484
                        unsigned short nbtdata[4];
485
                        nubus_get_rsrc_mem(nbtdata, &ent, 8);
486
                        dev->category = nbtdata[0];
487
                        dev->type     = nbtdata[1];
488
                        dev->dr_sw    = nbtdata[2];
489
                        dev->dr_hw    = nbtdata[3];
490
                        printk(KERN_INFO "    type: [cat 0x%x type 0x%x hw 0x%x sw 0x%x]\n",
491
                               nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
492
                        break;
493
                }
494
                case NUBUS_RESID_NAME:
495
                {
496
                        nubus_get_rsrc_str(dev->name, &ent, 64);
497
                        printk(KERN_INFO "    name: %s\n", dev->name);
498
                        break;
499
                }
500
                case NUBUS_RESID_DRVRDIR:
501
                {
502
                        /* MacOS driver.  If we were NetBSD we might
503
                           use this :-) */
504
                        struct nubus_dir drvr_dir;
505
                        struct nubus_dirent drvr_ent;
506
                        nubus_get_subdir(&ent, &drvr_dir);
507
                        nubus_readdir(&drvr_dir, &drvr_ent);
508
                        dev->driver = nubus_dirptr(&drvr_ent);
509
                        printk(KERN_INFO "    driver at: 0x%p\n",
510
                               dev->driver);
511
                        break;
512
                }
513
                case NUBUS_RESID_MINOR_BASEOS:
514
                        /* We will need this in order to support
515
                           multiple framebuffers.  It might be handy
516
                           for Ethernet as well */
517
                        nubus_get_rsrc_mem(&dev->iobase, &ent, 4);
518
                        printk(KERN_INFO "    memory offset: 0x%08lx\n",
519
                               dev->iobase);
520
                        break;
521
                case NUBUS_RESID_MINOR_LENGTH:
522
                        /* Ditto */
523
                        nubus_get_rsrc_mem(&dev->iosize, &ent, 4);
524
                        printk(KERN_INFO "    memory length: 0x%08lx\n",
525
                               dev->iosize);
526
                        break;
527
                case NUBUS_RESID_FLAGS:
528
                        dev->flags = ent.data;
529
                        printk(KERN_INFO "    flags: 0x%06x\n", dev->flags);
530
                        break;
531
                case NUBUS_RESID_HWDEVID:
532
                        dev->hwdevid = ent.data;
533
                        printk(KERN_INFO "    hwdevid: 0x%06x\n", dev->hwdevid);
534
                        break;
535
                default:
536
                        /* Local/Private resources have their own
537
                           function */
538
                        nubus_show_private_resource(dev, &ent);
539
                }
540
        }
541
 
542
        return dev;
543
}
544
 
545
/* This is cool. */
546
static int __init nubus_get_vidnames(struct nubus_board* board,
547
                                     const struct nubus_dirent* parent)
548
{
549
        struct nubus_dir    dir;
550
        struct nubus_dirent ent;
551
        /* FIXME: obviously we want to put this in a header file soon */
552
        struct vidmode {
553
                u32 size;
554
                /* Don't know what this is yet */
555
                u16 id;
556
                /* Longest one I've seen so far is 26 characters */
557
                char name[32];
558
        };
559
 
560
        printk(KERN_INFO "    video modes supported:\n");
561
        nubus_get_subdir(parent, &dir);
562
        if (console_loglevel >= 10)
563
                printk(KERN_DEBUG "nubus_get_vidnames: parent is 0x%p, dir is 0x%p\n",
564
                       parent->base, dir.base);
565
 
566
        while(nubus_readdir(&dir, &ent) != -1)
567
        {
568
                struct vidmode mode;
569
                u32 size;
570
 
571
                /* First get the length */
572
                nubus_get_rsrc_mem(&size, &ent, 4);
573
 
574
                /* Now clobber the whole thing */
575
                if (size > sizeof(mode) - 1)
576
                        size = sizeof(mode) - 1;
577
                memset(&mode, 0, sizeof(mode));
578
                nubus_get_rsrc_mem(&mode, &ent, size);
579
                printk (KERN_INFO "      %02X: (%02X) %s\n", ent.type,
580
                        mode.id, mode.name);
581
        }
582
        return 0;
583
}
584
 
585
/* This is *really* cool. */
586
static int __init nubus_get_icon(struct nubus_board* board,
587
                                 const struct nubus_dirent* ent)
588
{
589
        /* Should be 32x32 if my memory serves me correctly */
590
        unsigned char icon[128];
591
        int x, y;
592
 
593
        nubus_get_rsrc_mem(&icon, ent, 128);
594
        printk(KERN_INFO "    icon:\n");
595
 
596
        /* We should actually plot these somewhere in the framebuffer
597
           init.  This is just to demonstrate that they do, in fact,
598
           exist */
599
        for (y = 0; y < 32; y++) {
600
                printk(KERN_INFO "      ");
601
                for (x = 0; x < 32; x++) {
602
                        if (icon[y*4 + x/8]
603
                            & (0x80 >> (x%8)))
604
                                printk("*");
605
                        else
606
                                printk(" ");
607
                }
608
                printk("\n");
609
        }
610
        return 0;
611
}
612
 
613
static int __init nubus_get_vendorinfo(struct nubus_board* board,
614
                                       const struct nubus_dirent* parent)
615
{
616
        struct nubus_dir    dir;
617
        struct nubus_dirent ent;
618
        static char* vendor_fields[6] = {"ID", "serial", "revision",
619
                                         "part", "date", "unknown field"};
620
 
621
        printk(KERN_INFO "    vendor info:\n");
622
        nubus_get_subdir(parent, &dir);
623
        if (console_loglevel >= 10)
624
                printk(KERN_DEBUG "nubus_get_vendorinfo: parent is 0x%p, dir is 0x%p\n",
625
                       parent->base, dir.base);
626
 
627
        while(nubus_readdir(&dir, &ent) != -1)
628
        {
629
                char name[64];
630
 
631
                /* These are all strings, we think */
632
                nubus_get_rsrc_str(name, &ent, 64);
633
                if (ent.type > 5)
634
                        ent.type = 5;
635
                printk(KERN_INFO "    %s: %s\n",
636
                       vendor_fields[ent.type-1], name);
637
        }
638
        return 0;
639
}
640
 
641
static int __init nubus_get_board_resource(struct nubus_board* board, int slot,
642
                                           const struct nubus_dirent* parent)
643
{
644
        struct nubus_dir    dir;
645
        struct nubus_dirent ent;
646
 
647
        nubus_get_subdir(parent, &dir);
648
        if (console_loglevel >= 10)
649
                printk(KERN_DEBUG "nubus_get_board_resource: parent is 0x%p, dir is 0x%p\n",
650
                       parent->base, dir.base);
651
 
652
        while(nubus_readdir(&dir, &ent) != -1)
653
        {
654
                switch (ent.type) {
655
                case NUBUS_RESID_TYPE:
656
                {
657
                        unsigned short nbtdata[4];
658
                        /* This type is always the same, and is not
659
                           useful except insofar as it tells us that
660
                           we really are looking at a board resource. */
661
                        nubus_get_rsrc_mem(nbtdata, &ent, 8);
662
                        printk(KERN_INFO "    type: [cat 0x%x type 0x%x hw 0x%x sw 0x%x]\n",
663
                               nbtdata[0], nbtdata[1], nbtdata[2],
664
                               nbtdata[3]);
665
                        if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
666
                            nbtdata[2] != 0 || nbtdata[3] != 0)
667
                                printk(KERN_ERR "this sResource is not a board resource!\n");
668
                        break;
669
                }
670
                case NUBUS_RESID_NAME:
671
                        nubus_get_rsrc_str(board->name, &ent, 64);
672
                        printk(KERN_INFO "    name: %s\n", board->name);
673
                        break;
674
                case NUBUS_RESID_ICON:
675
                        nubus_get_icon(board, &ent);
676
                        break;
677
                case NUBUS_RESID_BOARDID:
678
                        printk(KERN_INFO "    board id: 0x%x\n", ent.data);
679
                        break;
680
                case NUBUS_RESID_PRIMARYINIT:
681
                        printk(KERN_INFO "    primary init offset: 0x%06x\n", ent.data);
682
                        break;
683
                case NUBUS_RESID_VENDORINFO:
684
                        nubus_get_vendorinfo(board, &ent);
685
                        break;
686
                case NUBUS_RESID_FLAGS:
687
                        printk(KERN_INFO "    flags: 0x%06x\n", ent.data);
688
                        break;
689
                case NUBUS_RESID_HWDEVID:
690
                        printk(KERN_INFO "    hwdevid: 0x%06x\n", ent.data);
691
                        break;
692
                case NUBUS_RESID_SECONDINIT:
693
                        printk(KERN_INFO "    secondary init offset: 0x%06x\n", ent.data);
694
                        break;
695
                        /* WTF isn't this in the functional resources? */
696
                case NUBUS_RESID_VIDNAMES:
697
                        nubus_get_vidnames(board, &ent);
698
                        break;
699
                        /* Same goes for this */
700
                case NUBUS_RESID_VIDMODES:
701
                        printk(KERN_INFO "    video mode parameter directory offset: 0x%06x\n",
702
                               ent.data);
703
                        break;
704
                default:
705
                        printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
706
                               ent.type, ent.data);
707
                }
708
        }
709
        return 0;
710
}
711
 
712
/* Attempt to bypass the somewhat non-obvious arrangement of
713
   sResources in the motherboard ROM */
714
static void __init nubus_find_rom_dir(struct nubus_board* board)
715
{
716
        unsigned char* rp;
717
        unsigned char* romdir;
718
        struct nubus_dir dir;
719
        struct nubus_dirent ent;
720
 
721
        /* Check for the extra directory just under the format block */
722
        rp = board->fblock;
723
        nubus_rewind(&rp, 4, board->lanes);
724
        if (nubus_get_rom(&rp, 4, board->lanes) != NUBUS_TEST_PATTERN) {
725
                /* OK, the ROM was telling the truth */
726
                board->directory = board->fblock;
727
                nubus_move(&board->directory,
728
                           nubus_expand32(board->doffset),
729
                           board->lanes);
730
                return;
731
        }
732
 
733
        /* On "slot zero", you have to walk down a few more
734
           directories to get to the equivalent of a real card's root
735
           directory.  We don't know what they were smoking when they
736
           came up with this. */
737
        romdir = nubus_rom_addr(board->slot);
738
        nubus_rewind(&romdir, ROM_DIR_OFFSET, board->lanes);
739
        dir.base = dir.ptr = romdir;
740
        dir.done = 0;
741
        dir.mask = board->lanes;
742
 
743
        /* This one points to an "Unknown Macintosh" directory */
744
        if (nubus_readdir(&dir, &ent) == -1)
745
                goto badrom;
746
 
747
        if (console_loglevel >= 10)
748
                printk(KERN_INFO "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
749
        /* This one takes us to where we want to go. */
750
        if (nubus_readdir(&dir, &ent) == -1)
751
                goto badrom;
752
        if (console_loglevel >= 10)
753
                printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
754
        nubus_get_subdir(&ent, &dir);
755
 
756
        /* Resource ID 01, also an "Unknown Macintosh" */
757
        if (nubus_readdir(&dir, &ent) == -1)
758
                goto badrom;
759
        if (console_loglevel >= 10)
760
                printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
761
 
762
        /* FIXME: the first one is *not* always the right one.  We
763
           suspect this has something to do with the ROM revision.
764
           "The HORROR ROM" (LC-series) uses 0x7e, while "The HORROR
765
           Continues" (Q630) uses 0x7b.  The DAFB Macs evidently use
766
           something else.  Please run "Slots" on your Mac (see
767
           include/linux/nubus.h for where to get this program) and
768
           tell us where the 'SiDirPtr' for Slot 0 is.  If you feel
769
           brave, you should also use MacsBug to walk down the ROM
770
           directories like this function does and try to find the
771
           path to that address... */
772
        if (nubus_readdir(&dir, &ent) == -1)
773
                goto badrom;
774
        if (console_loglevel >= 10)
775
                printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
776
 
777
        /* Bwahahahaha... */
778
        nubus_get_subdir(&ent, &dir);
779
        board->directory = dir.base;
780
        return;
781
 
782
        /* Even more evil laughter... */
783
 badrom:
784
        board->directory = board->fblock;
785
        nubus_move(&board->directory, nubus_expand32(board->doffset), board->lanes);
786
        printk(KERN_ERR "nubus_get_rom_dir: ROM weirdness!  Notify the developers...\n");
787
}
788
 
789
/* Add a board (might be many devices) to the list */
790
static struct nubus_board* __init nubus_add_board(int slot, int bytelanes)
791
{
792
        struct nubus_board* board;
793
        struct nubus_board** boardp;
794
 
795
        unsigned char *rp;
796
        unsigned long dpat;
797
        struct nubus_dir dir;
798
        struct nubus_dirent ent;
799
 
800
        /* Move to the start of the format block */
801
        rp = nubus_rom_addr(slot);
802
        nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
803
 
804
        /* Actually we should probably panic if this fails */
805
        if ((board = kmalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
806
                return NULL;
807
        memset(board, 0, sizeof(*board));
808
        board->fblock = rp;
809
 
810
        /* Dump the format block for debugging purposes */
811
        if (console_loglevel >= 10) {
812
                int i;
813
                printk(KERN_DEBUG "Slot %X, format block at 0x%p\n",
814
                       slot, rp);
815
                printk(KERN_DEBUG "Format block: ");
816
                for (i = 0; i < FORMAT_BLOCK_SIZE; i += 4) {
817
                        unsigned short foo, bar;
818
                        foo = nubus_get_rom(&rp, 2, bytelanes);
819
                        bar = nubus_get_rom(&rp, 2, bytelanes);
820
                        printk("%04x %04x  ", foo, bar);
821
                }
822
                printk("\n");
823
                rp = board->fblock;
824
        }
825
 
826
        board->slot = slot;
827
        board->slot_addr = (unsigned long) nubus_slot_addr(slot);
828
        board->doffset = nubus_get_rom(&rp, 4, bytelanes);
829
        /* rom_length is *supposed* to be the total length of the
830
         * ROM.  In practice it is the "amount of ROM used to compute
831
         * the CRC."  So some jokers decide to set it to zero and
832
         * set the crc to zero so they don't have to do any math.
833
         * See the Performa 460 ROM, for example.  Those Apple "engineers".
834
         */
835
        board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
836
        board->crc = nubus_get_rom(&rp, 4, bytelanes);
837
        board->rev = nubus_get_rom(&rp, 1, bytelanes);
838
        board->format = nubus_get_rom(&rp,1, bytelanes);
839
        board->lanes = bytelanes;
840
 
841
        /* Directory offset should be small and negative... */
842
        if(!(board->doffset & 0x00FF0000))
843
                printk(KERN_WARNING "Dodgy doffset!\n");
844
        dpat = nubus_get_rom(&rp, 4, bytelanes);
845
        if(dpat != NUBUS_TEST_PATTERN)
846
                printk(KERN_WARNING "Wrong test pattern %08lx!\n", dpat);
847
 
848
        /*
849
         *      I wonder how the CRC is meant to work -
850
         *              any takers ?
851
         * CSA: According to MAC docs, not all cards pass the CRC anyway,
852
         * since the initial Macintosh ROM releases skipped the check.
853
         */
854
 
855
        /* Attempt to work around slot zero weirdness */
856
        nubus_find_rom_dir(board);
857
        nubus_get_root_dir(board, &dir);
858
 
859
        /* We're ready to rock */
860
        printk(KERN_INFO "Slot %X:\n", slot);
861
 
862
        /* Each slot should have one board resource and any number of
863
           functional resources.  So we'll fill in some fields in the
864
           struct nubus_board from the board resource, then walk down
865
           the list of functional resources, spinning out a nubus_dev
866
           for each of them. */
867
        if (nubus_readdir(&dir, &ent) == -1) {
868
                /* We can't have this! */
869
                printk(KERN_ERR "Board resource not found!\n");
870
                return NULL;
871
        } else {
872
                printk(KERN_INFO "  Board resource:\n");
873
                nubus_get_board_resource(board, slot, &ent);
874
        }
875
 
876
        /* Aaaarrrrgghh!  The LC III motherboard has *two* board
877
           resources.  I have no idea WTF to do about this. */
878
 
879
        while (nubus_readdir(&dir, &ent) != -1) {
880
                struct nubus_dev*  dev;
881
                struct nubus_dev** devp;
882
                dev = nubus_get_functional_resource(board, slot, &ent);
883
                if (dev == NULL)
884
                        continue;
885
 
886
                /* We zeroed this out above */
887
                if (board->first_dev == NULL)
888
                        board->first_dev = dev;
889
 
890
                /* Put it on the global NuBus device chain. Keep entries in order. */
891
                for (devp=&nubus_devices; *devp!=NULL; devp=&((*devp)->next))
892
                        /* spin */;
893
                *devp = dev;
894
                dev->next = NULL;
895
        }
896
 
897
        /* Put it on the global NuBus board chain. Keep entries in order. */
898
        for (boardp=&nubus_boards; *boardp!=NULL; boardp=&((*boardp)->next))
899
                /* spin */;
900
        *boardp = board;
901
        board->next = NULL;
902
 
903
        return board;
904
}
905
 
906
void __init nubus_probe_slot(int slot)
907
{
908
        unsigned char dp;
909
        unsigned char* rp;
910
        int i;
911
 
912
        rp = nubus_rom_addr(slot);
913
        for(i = 4; i; i--)
914
        {
915
                unsigned long flags;
916
                int card_present;
917
 
918
                rp--;
919
                save_flags(flags);
920
                cli();
921
                card_present = hwreg_present(rp);
922
                restore_flags(flags);
923
 
924
                if (!card_present)
925
                        continue;
926
 
927
                printk(KERN_DEBUG "Now probing slot %X at %p\n", slot, rp);
928
                dp = *rp;
929
                if(dp == 0)
930
                        continue;
931
 
932
                /* The last byte of the format block consists of two
933
                   nybbles which are "mirror images" of each other.
934
                   These show us the valid bytelanes */
935
                if ((((dp>>4) ^ dp) & 0x0F) != 0x0F)
936
                        continue;
937
                /* Check that this value is actually *on* one of the
938
                   bytelanes it claims are valid! */
939
                if ((dp & 0x0F) >= (1<<i))
940
                        continue;
941
 
942
                /* Looks promising.  Let's put it on the list. */
943
                nubus_add_board(slot, dp);
944
 
945
                return;
946
        }
947
}
948
 
949
#if defined(CONFIG_PROC_FS)
950
 
951
/* /proc/nubus stuff */
952
 
953
static int sprint_nubus_board(struct nubus_board* board, char* ptr, int len)
954
{
955
        if(len < 100)
956
                return -1;
957
 
958
        sprintf(ptr, "Slot %X: %s\n",
959
                board->slot, board->name);
960
 
961
        return strlen(ptr);
962
}
963
 
964
static int nubus_read_proc(char *page, char **start, off_t off,
965
                                int count, int *eof, void *data)
966
{
967
        int nprinted, len, begin = 0;
968
        int size = PAGE_SIZE;
969
        struct nubus_board* board;
970
 
971
        len   = sprintf(page, "Nubus devices found:\n");
972
        /* Walk the list of NuBus boards */
973
        for (board = nubus_boards; board != NULL; board = board->next)
974
        {
975
                nprinted = sprint_nubus_board(board, page + len, size - len);
976
                if (nprinted < 0)
977
                        break;
978
                len += nprinted;
979
                if (len+begin < off) {
980
                        begin += len;
981
                        len = 0;
982
                }
983
                if (len+begin >= off+count)
984
                        break;
985
        }
986
        if (len+begin < off)
987
                *eof = 1;
988
        off -= begin;
989
        *start = page + off;
990
        len -= off;
991
        if (len>count)
992
                len = count;
993
        if (len<0)
994
                len = 0;
995
        return len;
996
}
997
#endif
998
 
999
void __init nubus_scan_bus(void)
1000
{
1001
        int slot;
1002
        /* This might not work on your machine */
1003
#ifdef I_WANT_TO_PROBE_SLOT_ZERO
1004
        nubus_probe_slot(0);
1005
#endif
1006
        for(slot = 9; slot < 15; slot++)
1007
        {
1008
                nubus_probe_slot(slot);
1009
        }
1010
}
1011
 
1012
void __init nubus_init(void)
1013
{
1014
        if (!MACH_IS_MAC)
1015
                return;
1016
 
1017
        /* Initialize the NuBus interrupts */
1018
        if (oss_present) {
1019
                oss_nubus_init();
1020
        } else {
1021
                via_nubus_init();
1022
        }
1023
 
1024
#ifdef TRY_TO_DODGE_WSOD
1025
        /* Rogue Ethernet interrupts can kill the machine if we don't
1026
           do this.  Obviously this is bogus.  Hopefully the local VIA
1027
           gurus can fix the real cause of the problem. */
1028
        mdelay(1000);
1029
#endif
1030
 
1031
        /* And probe */
1032
        printk("NuBus: Scanning NuBus slots.\n");
1033
        nubus_devices = NULL;
1034
        nubus_boards  = NULL;
1035
        nubus_scan_bus();
1036
 
1037
#ifdef CONFIG_PROC_FS
1038
        create_proc_read_entry("nubus", 0, NULL, nubus_read_proc, NULL);
1039
        nubus_proc_init();
1040
#endif
1041
}

powered by: WebSVN 2.1.0

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