1
2
3
4
5
6
7
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 <linux/module.h>
18#include <linux/slab.h>
19#include <asm/setup.h>
20#include <asm/page.h>
21#include <asm/hwtest.h>
22#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
29
30
31
32#define FORMAT_BLOCK_SIZE 20
33#define ROM_DIR_OFFSET 0x24
34
35#define NUBUS_TEST_PATTERN 0x5A932BC7
36
37
38
39
40#undef I_WANT_TO_PROBE_SLOT_ZERO
41
42
43#undef TRY_TO_DODGE_WSOD
44
45
46
47struct nubus_dev* nubus_devices;
48struct nubus_board* nubus_boards;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
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
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++;
128 p++;
129 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
143
144
145
146
147
148
149static inline long nubus_expand32(long foo)
150{
151 if(foo & 0x00800000)
152 foo |= 0xFF000000;
153 return foo;
154}
155
156static inline void *nubus_rom_addr(int slot)
157{
158
159
160
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
169
170 nubus_move(&p, nubus_expand32(nd->data), nd->mask);
171
172 return p;
173}
174
175
176
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}
189EXPORT_SYMBOL(nubus_get_rsrc_mem);
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}
204EXPORT_SYMBOL(nubus_get_rsrc_str);
205
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}
214EXPORT_SYMBOL(nubus_get_root_dir);
215
216
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}
225EXPORT_SYMBOL(nubus_get_func_dir);
226
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
237
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}
244EXPORT_SYMBOL(nubus_get_board_dir);
245
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}
254EXPORT_SYMBOL(nubus_get_subdir);
255
256int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
257{
258 u32 resid;
259 if (nd->done)
260 return -1;
261
262
263 ent->base = nd->ptr;
264
265
266 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
267
268
269 if((resid&0xff000000) == 0xff000000)
270 {
271
272 nd->done = 1;
273 return -1;
274 }
275
276
277 ent->type = resid >> 24;
278
279 ent->data = resid & 0xffffff;
280 ent->mask = nd->mask;
281 return 0;
282}
283EXPORT_SYMBOL(nubus_readdir);
284
285int nubus_rewinddir(struct nubus_dir* dir)
286{
287 dir->ptr = dir->base;
288 return 0;
289}
290EXPORT_SYMBOL(nubus_rewinddir);
291
292
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}
314EXPORT_SYMBOL(nubus_find_device);
315
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}
332EXPORT_SYMBOL(nubus_find_type);
333
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}
348EXPORT_SYMBOL(nubus_find_slot);
349
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}
360EXPORT_SYMBOL(nubus_find_rsrc);
361
362
363
364
365
366
367
368
369
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
473 if (slot == 0 && (unsigned long)dir.base % 2)
474 dir.base += 1;
475
476 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
477 printk(KERN_DEBUG "nubus_get_functional_resource: parent is 0x%p, dir is 0x%p\n",
478 parent->base, dir.base);
479
480
481 if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL)
482 return NULL;
483 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
512
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
524
525
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
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
546
547 nubus_show_private_resource(dev, &ent);
548 }
549 }
550
551 return dev;
552}
553
554
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
561 struct vidmode {
562 u32 size;
563
564 u16 id;
565
566 char name[32];
567 };
568
569 printk(KERN_INFO " video modes supported:\n");
570 nubus_get_subdir(parent, &dir);
571 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
572 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
581 nubus_get_rsrc_mem(&size, &ent, 4);
582
583
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
595static int __init nubus_get_icon(struct nubus_board* board,
596 const struct nubus_dirent* ent)
597{
598
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
606
607
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);
632 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
633 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
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);
657 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
658 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
668
669
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
705 case NUBUS_RESID_VIDNAMES:
706 nubus_get_vidnames(board, &ent);
707 break;
708
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
722
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
731 rp = board->fblock;
732 nubus_rewind(&rp, 4, board->lanes);
733 if (nubus_get_rom(&rp, 4, board->lanes) != NUBUS_TEST_PATTERN) {
734
735 board->directory = board->fblock;
736 nubus_move(&board->directory,
737 nubus_expand32(board->doffset),
738 board->lanes);
739 return;
740 }
741
742
743
744
745
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
753 if (nubus_readdir(&dir, &ent) == -1)
754 goto badrom;
755
756 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
757 printk(KERN_INFO "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
758
759 if (nubus_readdir(&dir, &ent) == -1)
760 goto badrom;
761 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
762 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
763 nubus_get_subdir(&ent, &dir);
764
765
766 if (nubus_readdir(&dir, &ent) == -1)
767 goto badrom;
768 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
769 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
770
771
772
773
774
775
776
777
778
779
780
781 if (nubus_readdir(&dir, &ent) == -1)
782 goto badrom;
783 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
784 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
785
786
787 nubus_get_subdir(&ent, &dir);
788 board->directory = dir.base;
789 return;
790
791
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
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
810 rp = nubus_rom_addr(slot);
811 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
812
813
814 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
815 return NULL;
816 board->fblock = rp;
817
818
819 if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG) {
820 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
838
839
840
841
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
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
858
859
860
861
862
863
864 nubus_find_rom_dir(board);
865 nubus_get_root_dir(board, &dir);
866
867
868 printk(KERN_INFO "Slot %X:\n", slot);
869
870
871
872
873
874
875 if (nubus_readdir(&dir, &ent) == -1) {
876
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
885
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
895 if (board->first_dev == NULL)
896 board->first_dev = dev;
897
898
899 for (devp=&nubus_devices; *devp!=NULL; devp=&((*devp)->next))
900 ;
901 *devp = dev;
902 dev->next = NULL;
903 }
904
905
906 for (boardp=&nubus_boards; *boardp!=NULL; boardp=&((*boardp)->next))
907 ;
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 {
923 int card_present;
924
925 rp--;
926 card_present = hwreg_present(rp);
927 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
936
937
938 if ((((dp>>4) ^ dp) & 0x0F) != 0x0F)
939 continue;
940
941
942 if ((dp & 0x0F) >= (1<<i))
943 continue;
944
945
946 nubus_add_board(slot, dp);
947
948 return;
949 }
950}
951
952void __init nubus_scan_bus(void)
953{
954 int slot;
955
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
971 if (oss_present) {
972 oss_nubus_init();
973 } else {
974 via_nubus_init();
975 }
976
977#ifdef TRY_TO_DODGE_WSOD
978
979
980
981 mdelay(1000);
982#endif
983
984
985 printk("NuBus: Scanning NuBus slots.\n");
986 nubus_devices = NULL;
987 nubus_boards = NULL;
988 nubus_scan_bus();
989 nubus_proc_init();
990 return 0;
991}
992
993subsys_initcall(nubus_init);
994