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