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 <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
30
31
32
33#define FORMAT_BLOCK_SIZE 20
34#define ROM_DIR_OFFSET 0x24
35
36#define NUBUS_TEST_PATTERN 0x5A932BC7
37
38
39
40
41#undef I_WANT_TO_PROBE_SLOT_ZERO
42
43
44#undef TRY_TO_DODGE_WSOD
45
46
47
48struct nubus_dev* nubus_devices;
49struct nubus_board* nubus_boards;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
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
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
144
145
146
147
148
149
150static inline long nubus_expand32(long foo)
151{
152 if(foo & 0x00800000)
153 foo |= 0xFF000000;
154 return foo;
155}
156
157static inline void *nubus_rom_addr(int slot)
158{
159
160
161
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
170
171 nubus_move(&p, nubus_expand32(nd->data), nd->mask);
172
173 return p;
174}
175
176
177
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}
190EXPORT_SYMBOL(nubus_get_rsrc_mem);
191
192void nubus_get_rsrc_str(void *dest, const struct nubus_dirent* dirent,
193 int len)
194{
195 unsigned char *t=(unsigned char *)dest;
196 unsigned char *p = nubus_dirptr(dirent);
197 while(len)
198 {
199 *t = nubus_get_rom(&p, 1, dirent->mask);
200 if(!*t++)
201 break;
202 len--;
203 }
204}
205EXPORT_SYMBOL(nubus_get_rsrc_str);
206
207int nubus_get_root_dir(const struct nubus_board* board,
208 struct nubus_dir* dir)
209{
210 dir->ptr = dir->base = board->directory;
211 dir->done = 0;
212 dir->mask = board->lanes;
213 return 0;
214}
215EXPORT_SYMBOL(nubus_get_root_dir);
216
217
218int nubus_get_func_dir(const struct nubus_dev* dev,
219 struct nubus_dir* dir)
220{
221 dir->ptr = dir->base = dev->directory;
222 dir->done = 0;
223 dir->mask = dev->board->lanes;
224 return 0;
225}
226EXPORT_SYMBOL(nubus_get_func_dir);
227
228int nubus_get_board_dir(const struct nubus_board* board,
229 struct nubus_dir* dir)
230{
231 struct nubus_dirent ent;
232
233 dir->ptr = dir->base = board->directory;
234 dir->done = 0;
235 dir->mask = board->lanes;
236
237
238
239 if (nubus_readdir(dir, &ent) == -1)
240 return -1;
241 if (nubus_get_subdir(&ent, dir) == -1)
242 return -1;
243 return 0;
244}
245EXPORT_SYMBOL(nubus_get_board_dir);
246
247int nubus_get_subdir(const struct nubus_dirent *ent,
248 struct nubus_dir *dir)
249{
250 dir->ptr = dir->base = nubus_dirptr(ent);
251 dir->done = 0;
252 dir->mask = ent->mask;
253 return 0;
254}
255EXPORT_SYMBOL(nubus_get_subdir);
256
257int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
258{
259 u32 resid;
260 if (nd->done)
261 return -1;
262
263
264 ent->base = nd->ptr;
265
266
267 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
268
269
270 if((resid&0xff000000) == 0xff000000)
271 {
272
273 nd->done = 1;
274 return -1;
275 }
276
277
278 ent->type = resid >> 24;
279
280 ent->data = resid & 0xffffff;
281 ent->mask = nd->mask;
282 return 0;
283}
284EXPORT_SYMBOL(nubus_readdir);
285
286int nubus_rewinddir(struct nubus_dir* dir)
287{
288 dir->ptr = dir->base;
289 return 0;
290}
291EXPORT_SYMBOL(nubus_rewinddir);
292
293
294
295struct nubus_dev*
296nubus_find_device(unsigned short category,
297 unsigned short type,
298 unsigned short dr_hw,
299 unsigned short dr_sw,
300 const struct nubus_dev* from)
301{
302 struct nubus_dev* itor =
303 from ? from->next : nubus_devices;
304
305 while (itor) {
306 if (itor->category == category
307 && itor->type == type
308 && itor->dr_hw == dr_hw
309 && itor->dr_sw == dr_sw)
310 return itor;
311 itor = itor->next;
312 }
313 return NULL;
314}
315EXPORT_SYMBOL(nubus_find_device);
316
317struct nubus_dev*
318nubus_find_type(unsigned short category,
319 unsigned short type,
320 const struct nubus_dev* from)
321{
322 struct nubus_dev* itor =
323 from ? from->next : nubus_devices;
324
325 while (itor) {
326 if (itor->category == category
327 && itor->type == type)
328 return itor;
329 itor = itor->next;
330 }
331 return NULL;
332}
333EXPORT_SYMBOL(nubus_find_type);
334
335struct nubus_dev*
336nubus_find_slot(unsigned int slot,
337 const struct nubus_dev* from)
338{
339 struct nubus_dev* itor =
340 from ? from->next : nubus_devices;
341
342 while (itor) {
343 if (itor->board->slot == slot)
344 return itor;
345 itor = itor->next;
346 }
347 return NULL;
348}
349EXPORT_SYMBOL(nubus_find_slot);
350
351int
352nubus_find_rsrc(struct nubus_dir* dir, unsigned char rsrc_type,
353 struct nubus_dirent* ent)
354{
355 while (nubus_readdir(dir, ent) != -1) {
356 if (ent->type == rsrc_type)
357 return 0;
358 }
359 return -1;
360}
361EXPORT_SYMBOL(nubus_find_rsrc);
362
363
364
365
366
367
368
369
370
371
372static int __init nubus_show_display_resource(struct nubus_dev* dev,
373 const struct nubus_dirent* ent)
374{
375 switch (ent->type) {
376 case NUBUS_RESID_GAMMADIR:
377 printk(KERN_INFO " gamma directory offset: 0x%06x\n", ent->data);
378 break;
379 case 0x0080 ... 0x0085:
380 printk(KERN_INFO " mode %02X info offset: 0x%06x\n",
381 ent->type, ent->data);
382 break;
383 default:
384 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
385 ent->type, ent->data);
386 }
387 return 0;
388}
389
390static int __init nubus_show_network_resource(struct nubus_dev* dev,
391 const struct nubus_dirent* ent)
392{
393 switch (ent->type) {
394 case NUBUS_RESID_MAC_ADDRESS:
395 {
396 char addr[6];
397 int i;
398
399 nubus_get_rsrc_mem(addr, ent, 6);
400 printk(KERN_INFO " MAC address: ");
401 for (i = 0; i < 6; i++)
402 printk("%02x%s", addr[i] & 0xff,
403 i == 5 ? "" : ":");
404 printk("\n");
405 break;
406 }
407 default:
408 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
409 ent->type, ent->data);
410 }
411 return 0;
412}
413
414static int __init nubus_show_cpu_resource(struct nubus_dev* dev,
415 const struct nubus_dirent* ent)
416{
417 switch (ent->type) {
418 case NUBUS_RESID_MEMINFO:
419 {
420 unsigned long meminfo[2];
421 nubus_get_rsrc_mem(&meminfo, ent, 8);
422 printk(KERN_INFO " memory: [ 0x%08lx 0x%08lx ]\n",
423 meminfo[0], meminfo[1]);
424 break;
425 }
426 case NUBUS_RESID_ROMINFO:
427 {
428 unsigned long rominfo[2];
429 nubus_get_rsrc_mem(&rominfo, ent, 8);
430 printk(KERN_INFO " ROM: [ 0x%08lx 0x%08lx ]\n",
431 rominfo[0], rominfo[1]);
432 break;
433 }
434 default:
435 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
436 ent->type, ent->data);
437 }
438 return 0;
439}
440
441static int __init nubus_show_private_resource(struct nubus_dev* dev,
442 const struct nubus_dirent* ent)
443{
444 switch (dev->category) {
445 case NUBUS_CAT_DISPLAY:
446 nubus_show_display_resource(dev, ent);
447 break;
448 case NUBUS_CAT_NETWORK:
449 nubus_show_network_resource(dev, ent);
450 break;
451 case NUBUS_CAT_CPU:
452 nubus_show_cpu_resource(dev, ent);
453 break;
454 default:
455 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
456 ent->type, ent->data);
457 }
458 return 0;
459}
460
461static struct nubus_dev* __init
462 nubus_get_functional_resource(struct nubus_board* board,
463 int slot,
464 const struct nubus_dirent* parent)
465{
466 struct nubus_dir dir;
467 struct nubus_dirent ent;
468 struct nubus_dev* dev;
469
470 printk(KERN_INFO " Function 0x%02x:\n", parent->type);
471 nubus_get_subdir(parent, &dir);
472
473
474 if (slot == 0 && (unsigned long)dir.base % 2)
475 dir.base += 1;
476
477 if (console_loglevel >= 10)
478 printk(KERN_DEBUG "nubus_get_functional_resource: parent is 0x%p, dir is 0x%p\n",
479 parent->base, dir.base);
480
481
482 if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL)
483 return NULL;
484 dev->resid = parent->type;
485 dev->directory = dir.base;
486 dev->board = board;
487
488 while (nubus_readdir(&dir, &ent) != -1)
489 {
490 switch(ent.type)
491 {
492 case NUBUS_RESID_TYPE:
493 {
494 unsigned short nbtdata[4];
495 nubus_get_rsrc_mem(nbtdata, &ent, 8);
496 dev->category = nbtdata[0];
497 dev->type = nbtdata[1];
498 dev->dr_sw = nbtdata[2];
499 dev->dr_hw = nbtdata[3];
500 printk(KERN_INFO " type: [cat 0x%x type 0x%x hw 0x%x sw 0x%x]\n",
501 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
502 break;
503 }
504 case NUBUS_RESID_NAME:
505 {
506 nubus_get_rsrc_str(dev->name, &ent, 64);
507 printk(KERN_INFO " name: %s\n", dev->name);
508 break;
509 }
510 case NUBUS_RESID_DRVRDIR:
511 {
512
513
514 struct nubus_dir drvr_dir;
515 struct nubus_dirent drvr_ent;
516 nubus_get_subdir(&ent, &drvr_dir);
517 nubus_readdir(&drvr_dir, &drvr_ent);
518 dev->driver = nubus_dirptr(&drvr_ent);
519 printk(KERN_INFO " driver at: 0x%p\n",
520 dev->driver);
521 break;
522 }
523 case NUBUS_RESID_MINOR_BASEOS:
524
525
526
527 nubus_get_rsrc_mem(&dev->iobase, &ent, 4);
528 printk(KERN_INFO " memory offset: 0x%08lx\n",
529 dev->iobase);
530 break;
531 case NUBUS_RESID_MINOR_LENGTH:
532
533 nubus_get_rsrc_mem(&dev->iosize, &ent, 4);
534 printk(KERN_INFO " memory length: 0x%08lx\n",
535 dev->iosize);
536 break;
537 case NUBUS_RESID_FLAGS:
538 dev->flags = ent.data;
539 printk(KERN_INFO " flags: 0x%06x\n", dev->flags);
540 break;
541 case NUBUS_RESID_HWDEVID:
542 dev->hwdevid = ent.data;
543 printk(KERN_INFO " hwdevid: 0x%06x\n", dev->hwdevid);
544 break;
545 default:
546
547
548 nubus_show_private_resource(dev, &ent);
549 }
550 }
551
552 return dev;
553}
554
555
556static int __init nubus_get_vidnames(struct nubus_board* board,
557 const struct nubus_dirent* parent)
558{
559 struct nubus_dir dir;
560 struct nubus_dirent ent;
561
562 struct vidmode {
563 u32 size;
564
565 u16 id;
566
567 char name[32];
568 };
569
570 printk(KERN_INFO " video modes supported:\n");
571 nubus_get_subdir(parent, &dir);
572 if (console_loglevel >= 10)
573 printk(KERN_DEBUG "nubus_get_vidnames: parent is 0x%p, dir is 0x%p\n",
574 parent->base, dir.base);
575
576 while(nubus_readdir(&dir, &ent) != -1)
577 {
578 struct vidmode mode;
579 u32 size;
580
581
582 nubus_get_rsrc_mem(&size, &ent, 4);
583
584
585 if (size > sizeof(mode) - 1)
586 size = sizeof(mode) - 1;
587 memset(&mode, 0, sizeof(mode));
588 nubus_get_rsrc_mem(&mode, &ent, size);
589 printk (KERN_INFO " %02X: (%02X) %s\n", ent.type,
590 mode.id, mode.name);
591 }
592 return 0;
593}
594
595
596static int __init nubus_get_icon(struct nubus_board* board,
597 const struct nubus_dirent* ent)
598{
599
600 unsigned char icon[128];
601 int x, y;
602
603 nubus_get_rsrc_mem(&icon, ent, 128);
604 printk(KERN_INFO " icon:\n");
605
606
607
608
609 for (y = 0; y < 32; y++) {
610 printk(KERN_INFO " ");
611 for (x = 0; x < 32; x++) {
612 if (icon[y*4 + x/8]
613 & (0x80 >> (x%8)))
614 printk("*");
615 else
616 printk(" ");
617 }
618 printk("\n");
619 }
620 return 0;
621}
622
623static int __init nubus_get_vendorinfo(struct nubus_board* board,
624 const struct nubus_dirent* parent)
625{
626 struct nubus_dir dir;
627 struct nubus_dirent ent;
628 static char* vendor_fields[6] = {"ID", "serial", "revision",
629 "part", "date", "unknown field"};
630
631 printk(KERN_INFO " vendor info:\n");
632 nubus_get_subdir(parent, &dir);
633 if (console_loglevel >= 10)
634 printk(KERN_DEBUG "nubus_get_vendorinfo: parent is 0x%p, dir is 0x%p\n",
635 parent->base, dir.base);
636
637 while(nubus_readdir(&dir, &ent) != -1)
638 {
639 char name[64];
640
641
642 nubus_get_rsrc_str(name, &ent, 64);
643 if (ent.type > 5)
644 ent.type = 5;
645 printk(KERN_INFO " %s: %s\n",
646 vendor_fields[ent.type-1], name);
647 }
648 return 0;
649}
650
651static int __init nubus_get_board_resource(struct nubus_board* board, int slot,
652 const struct nubus_dirent* parent)
653{
654 struct nubus_dir dir;
655 struct nubus_dirent ent;
656
657 nubus_get_subdir(parent, &dir);
658 if (console_loglevel >= 10)
659 printk(KERN_DEBUG "nubus_get_board_resource: parent is 0x%p, dir is 0x%p\n",
660 parent->base, dir.base);
661
662 while(nubus_readdir(&dir, &ent) != -1)
663 {
664 switch (ent.type) {
665 case NUBUS_RESID_TYPE:
666 {
667 unsigned short nbtdata[4];
668
669
670
671 nubus_get_rsrc_mem(nbtdata, &ent, 8);
672 printk(KERN_INFO " type: [cat 0x%x type 0x%x hw 0x%x sw 0x%x]\n",
673 nbtdata[0], nbtdata[1], nbtdata[2],
674 nbtdata[3]);
675 if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
676 nbtdata[2] != 0 || nbtdata[3] != 0)
677 printk(KERN_ERR "this sResource is not a board resource!\n");
678 break;
679 }
680 case NUBUS_RESID_NAME:
681 nubus_get_rsrc_str(board->name, &ent, 64);
682 printk(KERN_INFO " name: %s\n", board->name);
683 break;
684 case NUBUS_RESID_ICON:
685 nubus_get_icon(board, &ent);
686 break;
687 case NUBUS_RESID_BOARDID:
688 printk(KERN_INFO " board id: 0x%x\n", ent.data);
689 break;
690 case NUBUS_RESID_PRIMARYINIT:
691 printk(KERN_INFO " primary init offset: 0x%06x\n", ent.data);
692 break;
693 case NUBUS_RESID_VENDORINFO:
694 nubus_get_vendorinfo(board, &ent);
695 break;
696 case NUBUS_RESID_FLAGS:
697 printk(KERN_INFO " flags: 0x%06x\n", ent.data);
698 break;
699 case NUBUS_RESID_HWDEVID:
700 printk(KERN_INFO " hwdevid: 0x%06x\n", ent.data);
701 break;
702 case NUBUS_RESID_SECONDINIT:
703 printk(KERN_INFO " secondary init offset: 0x%06x\n", ent.data);
704 break;
705
706 case NUBUS_RESID_VIDNAMES:
707 nubus_get_vidnames(board, &ent);
708 break;
709
710 case NUBUS_RESID_VIDMODES:
711 printk(KERN_INFO " video mode parameter directory offset: 0x%06x\n",
712 ent.data);
713 break;
714 default:
715 printk(KERN_INFO " unknown resource %02X, data 0x%06x\n",
716 ent.type, ent.data);
717 }
718 }
719 return 0;
720}
721
722
723
724static void __init nubus_find_rom_dir(struct nubus_board* board)
725{
726 unsigned char* rp;
727 unsigned char* romdir;
728 struct nubus_dir dir;
729 struct nubus_dirent ent;
730
731
732 rp = board->fblock;
733 nubus_rewind(&rp, 4, board->lanes);
734 if (nubus_get_rom(&rp, 4, board->lanes) != NUBUS_TEST_PATTERN) {
735
736 board->directory = board->fblock;
737 nubus_move(&board->directory,
738 nubus_expand32(board->doffset),
739 board->lanes);
740 return;
741 }
742
743
744
745
746
747 romdir = nubus_rom_addr(board->slot);
748 nubus_rewind(&romdir, ROM_DIR_OFFSET, board->lanes);
749 dir.base = dir.ptr = romdir;
750 dir.done = 0;
751 dir.mask = board->lanes;
752
753
754 if (nubus_readdir(&dir, &ent) == -1)
755 goto badrom;
756
757 if (console_loglevel >= 10)
758 printk(KERN_INFO "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
759
760 if (nubus_readdir(&dir, &ent) == -1)
761 goto badrom;
762 if (console_loglevel >= 10)
763 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
764 nubus_get_subdir(&ent, &dir);
765
766
767 if (nubus_readdir(&dir, &ent) == -1)
768 goto badrom;
769 if (console_loglevel >= 10)
770 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
771
772
773
774
775
776
777
778
779
780
781
782 if (nubus_readdir(&dir, &ent) == -1)
783 goto badrom;
784 if (console_loglevel >= 10)
785 printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
786
787
788 nubus_get_subdir(&ent, &dir);
789 board->directory = dir.base;
790 return;
791
792
793 badrom:
794 board->directory = board->fblock;
795 nubus_move(&board->directory, nubus_expand32(board->doffset), board->lanes);
796 printk(KERN_ERR "nubus_get_rom_dir: ROM weirdness! Notify the developers...\n");
797}
798
799
800static struct nubus_board* __init nubus_add_board(int slot, int bytelanes)
801{
802 struct nubus_board* board;
803 struct nubus_board** boardp;
804
805 unsigned char *rp;
806 unsigned long dpat;
807 struct nubus_dir dir;
808 struct nubus_dirent ent;
809
810
811 rp = nubus_rom_addr(slot);
812 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
813
814
815 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
816 return NULL;
817 board->fblock = rp;
818
819
820 if (console_loglevel >= 10) {
821 int i;
822 printk(KERN_DEBUG "Slot %X, format block at 0x%p\n",
823 slot, rp);
824 printk(KERN_DEBUG "Format block: ");
825 for (i = 0; i < FORMAT_BLOCK_SIZE; i += 4) {
826 unsigned short foo, bar;
827 foo = nubus_get_rom(&rp, 2, bytelanes);
828 bar = nubus_get_rom(&rp, 2, bytelanes);
829 printk("%04x %04x ", foo, bar);
830 }
831 printk("\n");
832 rp = board->fblock;
833 }
834
835 board->slot = slot;
836 board->slot_addr = (unsigned long) nubus_slot_addr(slot);
837 board->doffset = nubus_get_rom(&rp, 4, bytelanes);
838
839
840
841
842
843
844 board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
845 board->crc = nubus_get_rom(&rp, 4, bytelanes);
846 board->rev = nubus_get_rom(&rp, 1, bytelanes);
847 board->format = nubus_get_rom(&rp,1, bytelanes);
848 board->lanes = bytelanes;
849
850
851 if(!(board->doffset & 0x00FF0000))
852 printk(KERN_WARNING "Dodgy doffset!\n");
853 dpat = nubus_get_rom(&rp, 4, bytelanes);
854 if(dpat != NUBUS_TEST_PATTERN)
855 printk(KERN_WARNING "Wrong test pattern %08lx!\n", dpat);
856
857
858
859
860
861
862
863
864
865 nubus_find_rom_dir(board);
866 nubus_get_root_dir(board, &dir);
867
868
869 printk(KERN_INFO "Slot %X:\n", slot);
870
871
872
873
874
875
876 if (nubus_readdir(&dir, &ent) == -1) {
877
878 printk(KERN_ERR "Board resource not found!\n");
879 return NULL;
880 } else {
881 printk(KERN_INFO " Board resource:\n");
882 nubus_get_board_resource(board, slot, &ent);
883 }
884
885
886
887
888 while (nubus_readdir(&dir, &ent) != -1) {
889 struct nubus_dev* dev;
890 struct nubus_dev** devp;
891 dev = nubus_get_functional_resource(board, slot, &ent);
892 if (dev == NULL)
893 continue;
894
895
896 if (board->first_dev == NULL)
897 board->first_dev = dev;
898
899
900 for (devp=&nubus_devices; *devp!=NULL; devp=&((*devp)->next))
901 ;
902 *devp = dev;
903 dev->next = NULL;
904 }
905
906
907 for (boardp=&nubus_boards; *boardp!=NULL; boardp=&((*boardp)->next))
908 ;
909 *boardp = board;
910 board->next = NULL;
911
912 return board;
913}
914
915void __init nubus_probe_slot(int slot)
916{
917 unsigned char dp;
918 unsigned char* rp;
919 int i;
920
921 rp = nubus_rom_addr(slot);
922 for(i = 4; i; i--)
923 {
924 unsigned long flags;
925 int card_present;
926
927 rp--;
928 local_irq_save(flags);
929 card_present = hwreg_present(rp);
930 local_irq_restore(flags);
931
932 if (!card_present)
933 continue;
934
935 printk(KERN_DEBUG "Now probing slot %X at %p\n", slot, rp);
936 dp = *rp;
937 if(dp == 0)
938 continue;
939
940
941
942
943 if ((((dp>>4) ^ dp) & 0x0F) != 0x0F)
944 continue;
945
946
947 if ((dp & 0x0F) >= (1<<i))
948 continue;
949
950
951 nubus_add_board(slot, dp);
952
953 return;
954 }
955}
956
957#if defined(CONFIG_PROC_FS)
958
959
960
961static int sprint_nubus_board(struct nubus_board* board, char* ptr, int len)
962{
963 if(len < 100)
964 return -1;
965
966 sprintf(ptr, "Slot %X: %s\n",
967 board->slot, board->name);
968
969 return strlen(ptr);
970}
971
972static int nubus_read_proc(char *page, char **start, off_t off,
973 int count, int *eof, void *data)
974{
975 int nprinted, len, begin = 0;
976 int size = PAGE_SIZE;
977 struct nubus_board* board;
978
979 len = sprintf(page, "Nubus devices found:\n");
980
981 for (board = nubus_boards; board != NULL; board = board->next)
982 {
983 nprinted = sprint_nubus_board(board, page + len, size - len);
984 if (nprinted < 0)
985 break;
986 len += nprinted;
987 if (len+begin < off) {
988 begin += len;
989 len = 0;
990 }
991 if (len+begin >= off+count)
992 break;
993 }
994 if (len+begin < off)
995 *eof = 1;
996 off -= begin;
997 *start = page + off;
998 len -= off;
999 if (len>count)
1000 len = count;
1001 if (len<0)
1002 len = 0;
1003 return len;
1004}
1005#endif
1006
1007void __init nubus_scan_bus(void)
1008{
1009 int slot;
1010
1011#ifdef I_WANT_TO_PROBE_SLOT_ZERO
1012 nubus_probe_slot(0);
1013#endif
1014 for(slot = 9; slot < 15; slot++)
1015 {
1016 nubus_probe_slot(slot);
1017 }
1018}
1019
1020static int __init nubus_init(void)
1021{
1022 if (!MACH_IS_MAC)
1023 return 0;
1024
1025
1026 if (oss_present) {
1027 oss_nubus_init();
1028 } else {
1029 via_nubus_init();
1030 }
1031
1032#ifdef TRY_TO_DODGE_WSOD
1033
1034
1035
1036 mdelay(1000);
1037#endif
1038
1039
1040 printk("NuBus: Scanning NuBus slots.\n");
1041 nubus_devices = NULL;
1042 nubus_boards = NULL;
1043 nubus_scan_bus();
1044
1045#ifdef CONFIG_PROC_FS
1046 create_proc_read_entry("nubus", 0, NULL, nubus_read_proc, NULL);
1047 nubus_proc_init();
1048#endif
1049 return 0;
1050}
1051
1052subsys_initcall(nubus_init);
1053