blob: 3319cf19deebe0f27a0243bb0661cebc24a3f74a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#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>
Adrian Bunk99ffab82008-02-04 22:30:23 -080017#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <asm/setup.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <asm/page.h>
21#include <asm/hwtest.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <asm/mac_via.h>
23#include <asm/mac_oss.h>
24
25extern void via_nubus_init(void);
26extern 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
47struct nubus_dev* nubus_devices;
48struct 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
73static 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
82static 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
100static 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
119static 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++;
Ilpo Järvinen2e0eb732008-10-15 22:01:31 -0700128 p++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 len--;
130 }
131 *ptr = p;
132}
133
134static 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
149static inline long nubus_expand32(long foo)
150{
151 if(foo & 0x00800000) /* 24bit negative */
152 foo |= 0xFF000000;
153 return foo;
154}
155
156static 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
165static 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
178void 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}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800189EXPORT_SYMBOL(nubus_get_rsrc_mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190
191void nubus_get_rsrc_str(void *dest, const struct nubus_dirent* dirent,
192 int len)
193{
194 unsigned char *t=(unsigned char *)dest;
195 unsigned char *p = nubus_dirptr(dirent);
196 while(len)
197 {
198 *t = nubus_get_rom(&p, 1, dirent->mask);
199 if(!*t++)
200 break;
201 len--;
202 }
203}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800204EXPORT_SYMBOL(nubus_get_rsrc_str);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
206int 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}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800214EXPORT_SYMBOL(nubus_get_root_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
216/* This is a slyly renamed version of the above */
217int nubus_get_func_dir(const struct nubus_dev* dev,
218 struct nubus_dir* dir)
219{
220 dir->ptr = dir->base = dev->directory;
221 dir->done = 0;
222 dir->mask = dev->board->lanes;
223 return 0;
224}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800225EXPORT_SYMBOL(nubus_get_func_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227int nubus_get_board_dir(const struct nubus_board* board,
228 struct nubus_dir* dir)
229{
230 struct nubus_dirent ent;
231
232 dir->ptr = dir->base = board->directory;
233 dir->done = 0;
234 dir->mask = board->lanes;
235
236 /* Now dereference it (the first directory is always the board
237 directory) */
238 if (nubus_readdir(dir, &ent) == -1)
239 return -1;
240 if (nubus_get_subdir(&ent, dir) == -1)
241 return -1;
242 return 0;
243}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800244EXPORT_SYMBOL(nubus_get_board_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
246int nubus_get_subdir(const struct nubus_dirent *ent,
247 struct nubus_dir *dir)
248{
249 dir->ptr = dir->base = nubus_dirptr(ent);
250 dir->done = 0;
251 dir->mask = ent->mask;
252 return 0;
253}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800254EXPORT_SYMBOL(nubus_get_subdir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
256int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
257{
258 u32 resid;
259 if (nd->done)
260 return -1;
261
262 /* Do this first, otherwise nubus_rewind & co are off by 4 */
263 ent->base = nd->ptr;
264
265 /* This moves nd->ptr forward */
266 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
267
268 /* EOL marker, as per the Apple docs */
269 if((resid&0xff000000) == 0xff000000)
270 {
271 /* Mark it as done */
272 nd->done = 1;
273 return -1;
274 }
275
276 /* First byte is the resource ID */
277 ent->type = resid >> 24;
278 /* Low 3 bytes might contain data (or might not) */
279 ent->data = resid & 0xffffff;
280 ent->mask = nd->mask;
281 return 0;
282}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800283EXPORT_SYMBOL(nubus_readdir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
285int nubus_rewinddir(struct nubus_dir* dir)
286{
287 dir->ptr = dir->base;
288 return 0;
289}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800290EXPORT_SYMBOL(nubus_rewinddir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
292/* Driver interface functions, more or less like in pci.c */
293
294struct nubus_dev*
295nubus_find_device(unsigned short category,
296 unsigned short type,
297 unsigned short dr_hw,
298 unsigned short dr_sw,
299 const struct nubus_dev* from)
300{
301 struct nubus_dev* itor =
302 from ? from->next : nubus_devices;
303
304 while (itor) {
305 if (itor->category == category
306 && itor->type == type
307 && itor->dr_hw == dr_hw
308 && itor->dr_sw == dr_sw)
309 return itor;
310 itor = itor->next;
311 }
312 return NULL;
313}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800314EXPORT_SYMBOL(nubus_find_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
316struct nubus_dev*
317nubus_find_type(unsigned short category,
318 unsigned short type,
319 const struct nubus_dev* from)
320{
321 struct nubus_dev* itor =
322 from ? from->next : nubus_devices;
323
324 while (itor) {
325 if (itor->category == category
326 && itor->type == type)
327 return itor;
328 itor = itor->next;
329 }
330 return NULL;
331}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800332EXPORT_SYMBOL(nubus_find_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334struct nubus_dev*
335nubus_find_slot(unsigned int slot,
336 const struct nubus_dev* from)
337{
338 struct nubus_dev* itor =
339 from ? from->next : nubus_devices;
340
341 while (itor) {
342 if (itor->board->slot == slot)
343 return itor;
344 itor = itor->next;
345 }
346 return NULL;
347}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800348EXPORT_SYMBOL(nubus_find_slot);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350int
351nubus_find_rsrc(struct nubus_dir* dir, unsigned char rsrc_type,
352 struct nubus_dirent* ent)
353{
354 while (nubus_readdir(dir, ent) != -1) {
355 if (ent->type == rsrc_type)
356 return 0;
357 }
358 return -1;
359}
Adrian Bunk99ffab82008-02-04 22:30:23 -0800360EXPORT_SYMBOL(nubus_find_rsrc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
362/* Initialization functions - decide which slots contain stuff worth
363 looking at, and print out lots and lots of information from the
364 resource blocks. */
365
366/* FIXME: A lot of this stuff will eventually be useful after
Joe Perches081985a2008-02-03 17:23:36 +0200367 initialization, for intelligently probing Ethernet and video chips,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 among other things. The rest of it should go in the /proc code.
369 For now, we just use it to give verbose boot logs. */
370
371static int __init nubus_show_display_resource(struct nubus_dev* dev,
372 const struct nubus_dirent* ent)
373{
374 switch (ent->type) {
375 case NUBUS_RESID_GAMMADIR:
376 printk(KERN_INFO " gamma directory offset: 0x%06x\n", ent->data);
377 break;
378 case 0x0080 ... 0x0085:
379 printk(KERN_INFO " mode %02X info offset: 0x%06x\n",
380 ent->type, ent->data);
381 break;
382 default:
383 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
384 ent->type, ent->data);
385 }
386 return 0;
387}
388
389static int __init nubus_show_network_resource(struct nubus_dev* dev,
390 const struct nubus_dirent* ent)
391{
392 switch (ent->type) {
393 case NUBUS_RESID_MAC_ADDRESS:
394 {
395 char addr[6];
396 int i;
397
398 nubus_get_rsrc_mem(addr, ent, 6);
399 printk(KERN_INFO " MAC address: ");
400 for (i = 0; i < 6; i++)
401 printk("%02x%s", addr[i] & 0xff,
402 i == 5 ? "" : ":");
403 printk("\n");
404 break;
405 }
406 default:
407 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
408 ent->type, ent->data);
409 }
410 return 0;
411}
412
413static int __init nubus_show_cpu_resource(struct nubus_dev* dev,
414 const struct nubus_dirent* ent)
415{
416 switch (ent->type) {
417 case NUBUS_RESID_MEMINFO:
418 {
419 unsigned long meminfo[2];
420 nubus_get_rsrc_mem(&meminfo, ent, 8);
421 printk(KERN_INFO " memory: [ 0x%08lx 0x%08lx ]\n",
422 meminfo[0], meminfo[1]);
423 break;
424 }
425 case NUBUS_RESID_ROMINFO:
426 {
427 unsigned long rominfo[2];
428 nubus_get_rsrc_mem(&rominfo, ent, 8);
429 printk(KERN_INFO " ROM: [ 0x%08lx 0x%08lx ]\n",
430 rominfo[0], rominfo[1]);
431 break;
432 }
433 default:
434 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
435 ent->type, ent->data);
436 }
437 return 0;
438}
439
440static int __init nubus_show_private_resource(struct nubus_dev* dev,
441 const struct nubus_dirent* ent)
442{
443 switch (dev->category) {
444 case NUBUS_CAT_DISPLAY:
445 nubus_show_display_resource(dev, ent);
446 break;
447 case NUBUS_CAT_NETWORK:
448 nubus_show_network_resource(dev, ent);
449 break;
450 case NUBUS_CAT_CPU:
451 nubus_show_cpu_resource(dev, ent);
452 break;
453 default:
454 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
455 ent->type, ent->data);
456 }
457 return 0;
458}
459
460static struct nubus_dev* __init
461 nubus_get_functional_resource(struct nubus_board* board,
462 int slot,
463 const struct nubus_dirent* parent)
464{
465 struct nubus_dir dir;
466 struct nubus_dirent ent;
467 struct nubus_dev* dev;
468
469 printk(KERN_INFO " Function 0x%02x:\n", parent->type);
470 nubus_get_subdir(parent, &dir);
471
472 /* Apple seems to have botched the ROM on the IIx */
473 if (slot == 0 && (unsigned long)dir.base % 2)
474 dir.base += 1;
475
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700476 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 printk(KERN_DEBUG "nubus_get_functional_resource: parent is 0x%p, dir is 0x%p\n",
478 parent->base, dir.base);
479
480 /* Actually we should probably panic if this fails */
Yoann Padioleaudd00cc42007-07-19 01:49:03 -0700481 if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 dev->resid = parent->type;
484 dev->directory = dir.base;
485 dev->board = board;
486
487 while (nubus_readdir(&dir, &ent) != -1)
488 {
489 switch(ent.type)
490 {
491 case NUBUS_RESID_TYPE:
492 {
493 unsigned short nbtdata[4];
494 nubus_get_rsrc_mem(nbtdata, &ent, 8);
495 dev->category = nbtdata[0];
496 dev->type = nbtdata[1];
497 dev->dr_sw = nbtdata[2];
498 dev->dr_hw = nbtdata[3];
499 printk(KERN_INFO " type: [cat 0x%x type 0x%x hw 0x%x sw 0x%x]\n",
500 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
501 break;
502 }
503 case NUBUS_RESID_NAME:
504 {
505 nubus_get_rsrc_str(dev->name, &ent, 64);
506 printk(KERN_INFO " name: %s\n", dev->name);
507 break;
508 }
509 case NUBUS_RESID_DRVRDIR:
510 {
511 /* MacOS driver. If we were NetBSD we might
512 use this :-) */
513 struct nubus_dir drvr_dir;
514 struct nubus_dirent drvr_ent;
515 nubus_get_subdir(&ent, &drvr_dir);
516 nubus_readdir(&drvr_dir, &drvr_ent);
517 dev->driver = nubus_dirptr(&drvr_ent);
518 printk(KERN_INFO " driver at: 0x%p\n",
519 dev->driver);
520 break;
521 }
522 case NUBUS_RESID_MINOR_BASEOS:
523 /* We will need this in order to support
524 multiple framebuffers. It might be handy
525 for Ethernet as well */
526 nubus_get_rsrc_mem(&dev->iobase, &ent, 4);
527 printk(KERN_INFO " memory offset: 0x%08lx\n",
528 dev->iobase);
529 break;
530 case NUBUS_RESID_MINOR_LENGTH:
531 /* Ditto */
532 nubus_get_rsrc_mem(&dev->iosize, &ent, 4);
533 printk(KERN_INFO " memory length: 0x%08lx\n",
534 dev->iosize);
535 break;
536 case NUBUS_RESID_FLAGS:
537 dev->flags = ent.data;
538 printk(KERN_INFO " flags: 0x%06x\n", dev->flags);
539 break;
540 case NUBUS_RESID_HWDEVID:
541 dev->hwdevid = ent.data;
542 printk(KERN_INFO " hwdevid: 0x%06x\n", dev->hwdevid);
543 break;
544 default:
545 /* Local/Private resources have their own
546 function */
547 nubus_show_private_resource(dev, &ent);
548 }
549 }
550
551 return dev;
552}
553
554/* This is cool. */
555static int __init nubus_get_vidnames(struct nubus_board* board,
556 const struct nubus_dirent* parent)
557{
558 struct nubus_dir dir;
559 struct nubus_dirent ent;
560 /* FIXME: obviously we want to put this in a header file soon */
561 struct vidmode {
562 u32 size;
563 /* Don't know what this is yet */
564 u16 id;
565 /* Longest one I've seen so far is 26 characters */
566 char name[32];
567 };
568
569 printk(KERN_INFO " video modes supported:\n");
570 nubus_get_subdir(parent, &dir);
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700571 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 printk(KERN_DEBUG "nubus_get_vidnames: parent is 0x%p, dir is 0x%p\n",
573 parent->base, dir.base);
574
575 while(nubus_readdir(&dir, &ent) != -1)
576 {
577 struct vidmode mode;
578 u32 size;
579
580 /* First get the length */
581 nubus_get_rsrc_mem(&size, &ent, 4);
582
583 /* Now clobber the whole thing */
584 if (size > sizeof(mode) - 1)
585 size = sizeof(mode) - 1;
586 memset(&mode, 0, sizeof(mode));
587 nubus_get_rsrc_mem(&mode, &ent, size);
588 printk (KERN_INFO " %02X: (%02X) %s\n", ent.type,
589 mode.id, mode.name);
590 }
591 return 0;
592}
593
594/* This is *really* cool. */
595static int __init nubus_get_icon(struct nubus_board* board,
596 const struct nubus_dirent* ent)
597{
598 /* Should be 32x32 if my memory serves me correctly */
599 unsigned char icon[128];
600 int x, y;
601
602 nubus_get_rsrc_mem(&icon, ent, 128);
603 printk(KERN_INFO " icon:\n");
604
605 /* We should actually plot these somewhere in the framebuffer
606 init. This is just to demonstrate that they do, in fact,
607 exist */
608 for (y = 0; y < 32; y++) {
609 printk(KERN_INFO " ");
610 for (x = 0; x < 32; x++) {
611 if (icon[y*4 + x/8]
612 & (0x80 >> (x%8)))
613 printk("*");
614 else
615 printk(" ");
616 }
617 printk("\n");
618 }
619 return 0;
620}
621
622static int __init nubus_get_vendorinfo(struct nubus_board* board,
623 const struct nubus_dirent* parent)
624{
625 struct nubus_dir dir;
626 struct nubus_dirent ent;
627 static char* vendor_fields[6] = {"ID", "serial", "revision",
628 "part", "date", "unknown field"};
629
630 printk(KERN_INFO " vendor info:\n");
631 nubus_get_subdir(parent, &dir);
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700632 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 printk(KERN_DEBUG "nubus_get_vendorinfo: parent is 0x%p, dir is 0x%p\n",
634 parent->base, dir.base);
635
636 while(nubus_readdir(&dir, &ent) != -1)
637 {
638 char name[64];
639
640 /* These are all strings, we think */
641 nubus_get_rsrc_str(name, &ent, 64);
642 if (ent.type > 5)
643 ent.type = 5;
644 printk(KERN_INFO " %s: %s\n",
645 vendor_fields[ent.type-1], name);
646 }
647 return 0;
648}
649
650static int __init nubus_get_board_resource(struct nubus_board* board, int slot,
651 const struct nubus_dirent* parent)
652{
653 struct nubus_dir dir;
654 struct nubus_dirent ent;
655
656 nubus_get_subdir(parent, &dir);
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700657 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 printk(KERN_DEBUG "nubus_get_board_resource: parent is 0x%p, dir is 0x%p\n",
659 parent->base, dir.base);
660
661 while(nubus_readdir(&dir, &ent) != -1)
662 {
663 switch (ent.type) {
664 case NUBUS_RESID_TYPE:
665 {
666 unsigned short nbtdata[4];
667 /* This type is always the same, and is not
668 useful except insofar as it tells us that
669 we really are looking at a board resource. */
670 nubus_get_rsrc_mem(nbtdata, &ent, 8);
671 printk(KERN_INFO " type: [cat 0x%x type 0x%x hw 0x%x sw 0x%x]\n",
672 nbtdata[0], nbtdata[1], nbtdata[2],
673 nbtdata[3]);
674 if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
675 nbtdata[2] != 0 || nbtdata[3] != 0)
676 printk(KERN_ERR "this sResource is not a board resource!\n");
677 break;
678 }
679 case NUBUS_RESID_NAME:
680 nubus_get_rsrc_str(board->name, &ent, 64);
681 printk(KERN_INFO " name: %s\n", board->name);
682 break;
683 case NUBUS_RESID_ICON:
684 nubus_get_icon(board, &ent);
685 break;
686 case NUBUS_RESID_BOARDID:
687 printk(KERN_INFO " board id: 0x%x\n", ent.data);
688 break;
689 case NUBUS_RESID_PRIMARYINIT:
690 printk(KERN_INFO " primary init offset: 0x%06x\n", ent.data);
691 break;
692 case NUBUS_RESID_VENDORINFO:
693 nubus_get_vendorinfo(board, &ent);
694 break;
695 case NUBUS_RESID_FLAGS:
696 printk(KERN_INFO " flags: 0x%06x\n", ent.data);
697 break;
698 case NUBUS_RESID_HWDEVID:
699 printk(KERN_INFO " hwdevid: 0x%06x\n", ent.data);
700 break;
701 case NUBUS_RESID_SECONDINIT:
702 printk(KERN_INFO " secondary init offset: 0x%06x\n", ent.data);
703 break;
704 /* WTF isn't this in the functional resources? */
705 case NUBUS_RESID_VIDNAMES:
706 nubus_get_vidnames(board, &ent);
707 break;
708 /* Same goes for this */
709 case NUBUS_RESID_VIDMODES:
710 printk(KERN_INFO " video mode parameter directory offset: 0x%06x\n",
711 ent.data);
712 break;
713 default:
714 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
715 ent.type, ent.data);
716 }
717 }
718 return 0;
719}
720
721/* Attempt to bypass the somewhat non-obvious arrangement of
722 sResources in the motherboard ROM */
723static void __init nubus_find_rom_dir(struct nubus_board* board)
724{
725 unsigned char* rp;
726 unsigned char* romdir;
727 struct nubus_dir dir;
728 struct nubus_dirent ent;
729
730 /* Check for the extra directory just under the format block */
731 rp = board->fblock;
732 nubus_rewind(&rp, 4, board->lanes);
733 if (nubus_get_rom(&rp, 4, board->lanes) != NUBUS_TEST_PATTERN) {
734 /* OK, the ROM was telling the truth */
735 board->directory = board->fblock;
736 nubus_move(&board->directory,
737 nubus_expand32(board->doffset),
738 board->lanes);
739 return;
740 }
741
742 /* On "slot zero", you have to walk down a few more
743 directories to get to the equivalent of a real card's root
744 directory. We don't know what they were smoking when they
745 came up with this. */
746 romdir = nubus_rom_addr(board->slot);
747 nubus_rewind(&romdir, ROM_DIR_OFFSET, board->lanes);
748 dir.base = dir.ptr = romdir;
749 dir.done = 0;
750 dir.mask = board->lanes;
751
752 /* This one points to an "Unknown Macintosh" directory */
753 if (nubus_readdir(&dir, &ent) == -1)
754 goto badrom;
755
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700756 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 printk(KERN_INFO "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
758 /* This one takes us to where we want to go. */
759 if (nubus_readdir(&dir, &ent) == -1)
760 goto badrom;
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700761 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
763 nubus_get_subdir(&ent, &dir);
764
765 /* Resource ID 01, also an "Unknown Macintosh" */
766 if (nubus_readdir(&dir, &ent) == -1)
767 goto badrom;
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700768 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
770
771 /* FIXME: the first one is *not* always the right one. We
772 suspect this has something to do with the ROM revision.
773 "The HORROR ROM" (LC-series) uses 0x7e, while "The HORROR
774 Continues" (Q630) uses 0x7b. The DAFB Macs evidently use
775 something else. Please run "Slots" on your Mac (see
776 include/linux/nubus.h for where to get this program) and
777 tell us where the 'SiDirPtr' for Slot 0 is. If you feel
778 brave, you should also use MacsBug to walk down the ROM
779 directories like this function does and try to find the
780 path to that address... */
781 if (nubus_readdir(&dir, &ent) == -1)
782 goto badrom;
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700783 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
785
786 /* Bwahahahaha... */
787 nubus_get_subdir(&ent, &dir);
788 board->directory = dir.base;
789 return;
790
791 /* Even more evil laughter... */
792 badrom:
793 board->directory = board->fblock;
794 nubus_move(&board->directory, nubus_expand32(board->doffset), board->lanes);
795 printk(KERN_ERR "nubus_get_rom_dir: ROM weirdness! Notify the developers...\n");
796}
797
798/* Add a board (might be many devices) to the list */
799static struct nubus_board* __init nubus_add_board(int slot, int bytelanes)
800{
801 struct nubus_board* board;
802 struct nubus_board** boardp;
803
804 unsigned char *rp;
805 unsigned long dpat;
806 struct nubus_dir dir;
807 struct nubus_dirent ent;
808
809 /* Move to the start of the format block */
810 rp = nubus_rom_addr(slot);
811 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
812
813 /* Actually we should probably panic if this fails */
Yoann Padioleaudd00cc42007-07-19 01:49:03 -0700814 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 board->fblock = rp;
817
818 /* Dump the format block for debugging purposes */
Borislav Petkova8fe19e2014-06-04 16:11:46 -0700819 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 int i;
821 printk(KERN_DEBUG "Slot %X, format block at 0x%p\n",
822 slot, rp);
823 printk(KERN_DEBUG "Format block: ");
824 for (i = 0; i < FORMAT_BLOCK_SIZE; i += 4) {
825 unsigned short foo, bar;
826 foo = nubus_get_rom(&rp, 2, bytelanes);
827 bar = nubus_get_rom(&rp, 2, bytelanes);
828 printk("%04x %04x ", foo, bar);
829 }
830 printk("\n");
831 rp = board->fblock;
832 }
833
834 board->slot = slot;
835 board->slot_addr = (unsigned long) nubus_slot_addr(slot);
836 board->doffset = nubus_get_rom(&rp, 4, bytelanes);
837 /* rom_length is *supposed* to be the total length of the
838 * ROM. In practice it is the "amount of ROM used to compute
839 * the CRC." So some jokers decide to set it to zero and
840 * set the crc to zero so they don't have to do any math.
841 * See the Performa 460 ROM, for example. Those Apple "engineers".
842 */
843 board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
844 board->crc = nubus_get_rom(&rp, 4, bytelanes);
845 board->rev = nubus_get_rom(&rp, 1, bytelanes);
846 board->format = nubus_get_rom(&rp,1, bytelanes);
847 board->lanes = bytelanes;
848
849 /* Directory offset should be small and negative... */
850 if(!(board->doffset & 0x00FF0000))
851 printk(KERN_WARNING "Dodgy doffset!\n");
852 dpat = nubus_get_rom(&rp, 4, bytelanes);
853 if(dpat != NUBUS_TEST_PATTERN)
854 printk(KERN_WARNING "Wrong test pattern %08lx!\n", dpat);
855
856 /*
857 * I wonder how the CRC is meant to work -
858 * any takers ?
859 * CSA: According to MAC docs, not all cards pass the CRC anyway,
860 * since the initial Macintosh ROM releases skipped the check.
861 */
862
863 /* Attempt to work around slot zero weirdness */
864 nubus_find_rom_dir(board);
865 nubus_get_root_dir(board, &dir);
866
867 /* We're ready to rock */
868 printk(KERN_INFO "Slot %X:\n", slot);
869
870 /* Each slot should have one board resource and any number of
871 functional resources. So we'll fill in some fields in the
872 struct nubus_board from the board resource, then walk down
873 the list of functional resources, spinning out a nubus_dev
874 for each of them. */
875 if (nubus_readdir(&dir, &ent) == -1) {
876 /* We can't have this! */
877 printk(KERN_ERR "Board resource not found!\n");
878 return NULL;
879 } else {
880 printk(KERN_INFO " Board resource:\n");
881 nubus_get_board_resource(board, slot, &ent);
882 }
883
884 /* Aaaarrrrgghh! The LC III motherboard has *two* board
885 resources. I have no idea WTF to do about this. */
886
887 while (nubus_readdir(&dir, &ent) != -1) {
888 struct nubus_dev* dev;
889 struct nubus_dev** devp;
890 dev = nubus_get_functional_resource(board, slot, &ent);
891 if (dev == NULL)
892 continue;
893
894 /* We zeroed this out above */
895 if (board->first_dev == NULL)
896 board->first_dev = dev;
897
898 /* Put it on the global NuBus device chain. Keep entries in order. */
899 for (devp=&nubus_devices; *devp!=NULL; devp=&((*devp)->next))
900 /* spin */;
901 *devp = dev;
902 dev->next = NULL;
903 }
904
905 /* Put it on the global NuBus board chain. Keep entries in order. */
906 for (boardp=&nubus_boards; *boardp!=NULL; boardp=&((*boardp)->next))
907 /* spin */;
908 *boardp = board;
909 board->next = NULL;
910
911 return board;
912}
913
914void __init nubus_probe_slot(int slot)
915{
916 unsigned char dp;
917 unsigned char* rp;
918 int i;
919
920 rp = nubus_rom_addr(slot);
921 for(i = 4; i; i--)
922 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 int card_present;
924
925 rp--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 card_present = hwreg_present(rp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (!card_present)
928 continue;
929
930 printk(KERN_DEBUG "Now probing slot %X at %p\n", slot, rp);
931 dp = *rp;
932 if(dp == 0)
933 continue;
934
935 /* The last byte of the format block consists of two
936 nybbles which are "mirror images" of each other.
937 These show us the valid bytelanes */
938 if ((((dp>>4) ^ dp) & 0x0F) != 0x0F)
939 continue;
940 /* Check that this value is actually *on* one of the
941 bytelanes it claims are valid! */
942 if ((dp & 0x0F) >= (1<<i))
943 continue;
944
945 /* Looks promising. Let's put it on the list. */
946 nubus_add_board(slot, dp);
947
948 return;
949 }
950}
951
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952void __init nubus_scan_bus(void)
953{
954 int slot;
955 /* This might not work on your machine */
956#ifdef I_WANT_TO_PROBE_SLOT_ZERO
957 nubus_probe_slot(0);
958#endif
959 for(slot = 9; slot < 15; slot++)
960 {
961 nubus_probe_slot(slot);
962 }
963}
964
965static int __init nubus_init(void)
966{
967 if (!MACH_IS_MAC)
968 return 0;
969
970 /* Initialize the NuBus interrupts */
971 if (oss_present) {
972 oss_nubus_init();
973 } else {
974 via_nubus_init();
975 }
976
977#ifdef TRY_TO_DODGE_WSOD
978 /* Rogue Ethernet interrupts can kill the machine if we don't
979 do this. Obviously this is bogus. Hopefully the local VIA
980 gurus can fix the real cause of the problem. */
981 mdelay(1000);
982#endif
983
984 /* And probe */
985 printk("NuBus: Scanning NuBus slots.\n");
986 nubus_devices = NULL;
987 nubus_boards = NULL;
988 nubus_scan_bus();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 nubus_proc_init();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 return 0;
991}
992
993subsys_initcall(nubus_init);