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