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