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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [drivers/] [nubus/] [nubus.c] - Blame information for rev 3

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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