1
2
3
4
5
6
7
8
9
10
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/module.h>
18#include <linux/seq_file.h>
19#include <linux/slab.h>
20#include <asm/setup.h>
21#include <asm/page.h>
22#include <asm/hwtest.h>
23
24
25
26
27
28#define FORMAT_BLOCK_SIZE 20
29#define ROM_DIR_OFFSET 0x24
30
31#define NUBUS_TEST_PATTERN 0x5A932BC7
32
33
34
35LIST_HEAD(nubus_func_rsrcs);
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60static inline int not_useful(void *p, int map)
61{
62 unsigned long pv = (unsigned long)p;
63
64 pv &= 3;
65 if (map & (1 << pv))
66 return 0;
67 return 1;
68}
69
70static unsigned long nubus_get_rom(unsigned char **ptr, int len, int map)
71{
72
73 unsigned long v = 0;
74 unsigned char *p = *ptr;
75
76 while (len) {
77 v <<= 8;
78 while (not_useful(p, map))
79 p++;
80 v |= *p++;
81 len--;
82 }
83 *ptr = p;
84 return v;
85}
86
87static void nubus_rewind(unsigned char **ptr, int len, int map)
88{
89 unsigned char *p = *ptr;
90
91 while (len) {
92 do {
93 p--;
94 } while (not_useful(p, map));
95 len--;
96 }
97 *ptr = p;
98}
99
100static void nubus_advance(unsigned char **ptr, int len, int map)
101{
102 unsigned char *p = *ptr;
103
104 while (len) {
105 while (not_useful(p, map))
106 p++;
107 p++;
108 len--;
109 }
110 *ptr = p;
111}
112
113static void nubus_move(unsigned char **ptr, int len, int map)
114{
115 unsigned long slot_space = (unsigned long)*ptr & 0xFF000000;
116
117 if (len > 0)
118 nubus_advance(ptr, len, map);
119 else if (len < 0)
120 nubus_rewind(ptr, -len, map);
121
122 if (((unsigned long)*ptr & 0xFF000000) != slot_space)
123 pr_err("%s: moved out of slot address space!\n", __func__);
124}
125
126
127
128
129
130
131
132
133static inline long nubus_expand32(long foo)
134{
135 if (foo & 0x00800000)
136 foo |= 0xFF000000;
137 return foo;
138}
139
140static inline void *nubus_rom_addr(int slot)
141{
142
143
144
145
146 return (void *)(0xF1000000 + (slot << 24));
147}
148
149unsigned char *nubus_dirptr(const struct nubus_dirent *nd)
150{
151 unsigned char *p = nd->base;
152
153
154
155 nubus_move(&p, nubus_expand32(nd->data), nd->mask);
156
157 return p;
158}
159
160
161
162
163void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
164 unsigned int len)
165{
166 unsigned char *t = (unsigned char *)dest;
167 unsigned char *p = nubus_dirptr(dirent);
168
169 while (len) {
170 *t++ = nubus_get_rom(&p, 1, dirent->mask);
171 len--;
172 }
173}
174EXPORT_SYMBOL(nubus_get_rsrc_mem);
175
176unsigned int nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
177 unsigned int len)
178{
179 char *t = dest;
180 unsigned char *p = nubus_dirptr(dirent);
181
182 while (len > 1) {
183 unsigned char c = nubus_get_rom(&p, 1, dirent->mask);
184
185 if (!c)
186 break;
187 *t++ = c;
188 len--;
189 }
190 if (len > 0)
191 *t = '\0';
192 return t - dest;
193}
194EXPORT_SYMBOL(nubus_get_rsrc_str);
195
196void nubus_seq_write_rsrc_mem(struct seq_file *m,
197 const struct nubus_dirent *dirent,
198 unsigned int len)
199{
200 unsigned long buf[32];
201 unsigned int buf_size = sizeof(buf);
202 unsigned char *p = nubus_dirptr(dirent);
203
204
205 while (len >= buf_size) {
206 unsigned int i;
207
208 for (i = 0; i < ARRAY_SIZE(buf); i++)
209 buf[i] = nubus_get_rom(&p, sizeof(buf[0]),
210 dirent->mask);
211 seq_write(m, buf, buf_size);
212 len -= buf_size;
213 }
214
215 while (len--)
216 seq_putc(m, nubus_get_rom(&p, 1, dirent->mask));
217}
218
219int nubus_get_root_dir(const struct nubus_board *board,
220 struct nubus_dir *dir)
221{
222 dir->ptr = dir->base = board->directory;
223 dir->done = 0;
224 dir->mask = board->lanes;
225 return 0;
226}
227EXPORT_SYMBOL(nubus_get_root_dir);
228
229
230int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir)
231{
232 dir->ptr = dir->base = fres->directory;
233 dir->done = 0;
234 dir->mask = fres->board->lanes;
235 return 0;
236}
237EXPORT_SYMBOL(nubus_get_func_dir);
238
239int nubus_get_board_dir(const struct nubus_board *board,
240 struct nubus_dir *dir)
241{
242 struct nubus_dirent ent;
243
244 dir->ptr = dir->base = board->directory;
245 dir->done = 0;
246 dir->mask = board->lanes;
247
248
249
250 if (nubus_readdir(dir, &ent) == -1)
251 return -1;
252 if (nubus_get_subdir(&ent, dir) == -1)
253 return -1;
254 return 0;
255}
256EXPORT_SYMBOL(nubus_get_board_dir);
257
258int nubus_get_subdir(const struct nubus_dirent *ent,
259 struct nubus_dir *dir)
260{
261 dir->ptr = dir->base = nubus_dirptr(ent);
262 dir->done = 0;
263 dir->mask = ent->mask;
264 return 0;
265}
266EXPORT_SYMBOL(nubus_get_subdir);
267
268int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
269{
270 u32 resid;
271
272 if (nd->done)
273 return -1;
274
275
276 ent->base = nd->ptr;
277
278
279 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
280
281
282 if ((resid & 0xff000000) == 0xff000000) {
283
284 nd->done = 1;
285 return -1;
286 }
287
288
289 ent->type = resid >> 24;
290
291 ent->data = resid & 0xffffff;
292 ent->mask = nd->mask;
293 return 0;
294}
295EXPORT_SYMBOL(nubus_readdir);
296
297int nubus_rewinddir(struct nubus_dir *dir)
298{
299 dir->ptr = dir->base;
300 dir->done = 0;
301 return 0;
302}
303EXPORT_SYMBOL(nubus_rewinddir);
304
305
306
307struct nubus_rsrc *nubus_first_rsrc_or_null(void)
308{
309 return list_first_entry_or_null(&nubus_func_rsrcs, struct nubus_rsrc,
310 list);
311}
312EXPORT_SYMBOL(nubus_first_rsrc_or_null);
313
314struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from)
315{
316 if (list_is_last(&from->list, &nubus_func_rsrcs))
317 return NULL;
318 return list_next_entry(from, list);
319}
320EXPORT_SYMBOL(nubus_next_rsrc_or_null);
321
322int
323nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type,
324 struct nubus_dirent *ent)
325{
326 while (nubus_readdir(dir, ent) != -1) {
327 if (ent->type == rsrc_type)
328 return 0;
329 }
330 return -1;
331}
332EXPORT_SYMBOL(nubus_find_rsrc);
333
334
335
336
337
338static int __init nubus_get_block_rsrc_dir(struct nubus_board *board,
339 struct proc_dir_entry *procdir,
340 const struct nubus_dirent *parent)
341{
342 struct nubus_dir dir;
343 struct nubus_dirent ent;
344
345 nubus_get_subdir(parent, &dir);
346 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
347
348 while (nubus_readdir(&dir, &ent) != -1) {
349 u32 size;
350
351 nubus_get_rsrc_mem(&size, &ent, 4);
352 pr_debug(" block (0x%x), size %d\n", ent.type, size);
353 nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
354 }
355 return 0;
356}
357
358static int __init nubus_get_display_vidmode(struct nubus_board *board,
359 struct proc_dir_entry *procdir,
360 const struct nubus_dirent *parent)
361{
362 struct nubus_dir dir;
363 struct nubus_dirent ent;
364
365 nubus_get_subdir(parent, &dir);
366 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
367
368 while (nubus_readdir(&dir, &ent) != -1) {
369 switch (ent.type) {
370 case 1:
371 case 2:
372 {
373 u32 size;
374
375 nubus_get_rsrc_mem(&size, &ent, 4);
376 pr_debug(" block (0x%x), size %d\n", ent.type,
377 size);
378 nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
379 break;
380 }
381 default:
382 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
383 ent.type, ent.data);
384 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
385 }
386 }
387 return 0;
388}
389
390static int __init nubus_get_display_resource(struct nubus_rsrc *fres,
391 struct proc_dir_entry *procdir,
392 const struct nubus_dirent *ent)
393{
394 switch (ent->type) {
395 case NUBUS_RESID_GAMMADIR:
396 pr_debug(" gamma directory offset: 0x%06x\n", ent->data);
397 nubus_get_block_rsrc_dir(fres->board, procdir, ent);
398 break;
399 case 0x0080 ... 0x0085:
400 pr_debug(" mode 0x%02x info offset: 0x%06x\n",
401 ent->type, ent->data);
402 nubus_get_display_vidmode(fres->board, procdir, ent);
403 break;
404 default:
405 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
406 ent->type, ent->data);
407 nubus_proc_add_rsrc_mem(procdir, ent, 0);
408 }
409 return 0;
410}
411
412static int __init nubus_get_network_resource(struct nubus_rsrc *fres,
413 struct proc_dir_entry *procdir,
414 const struct nubus_dirent *ent)
415{
416 switch (ent->type) {
417 case NUBUS_RESID_MAC_ADDRESS:
418 {
419 char addr[6];
420
421 nubus_get_rsrc_mem(addr, ent, 6);
422 pr_debug(" MAC address: %pM\n", addr);
423 nubus_proc_add_rsrc_mem(procdir, ent, 6);
424 break;
425 }
426 default:
427 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
428 ent->type, ent->data);
429 nubus_proc_add_rsrc_mem(procdir, ent, 0);
430 }
431 return 0;
432}
433
434static int __init nubus_get_cpu_resource(struct nubus_rsrc *fres,
435 struct proc_dir_entry *procdir,
436 const struct nubus_dirent *ent)
437{
438 switch (ent->type) {
439 case NUBUS_RESID_MEMINFO:
440 {
441 unsigned long meminfo[2];
442
443 nubus_get_rsrc_mem(&meminfo, ent, 8);
444 pr_debug(" memory: [ 0x%08lx 0x%08lx ]\n",
445 meminfo[0], meminfo[1]);
446 nubus_proc_add_rsrc_mem(procdir, ent, 8);
447 break;
448 }
449 case NUBUS_RESID_ROMINFO:
450 {
451 unsigned long rominfo[2];
452
453 nubus_get_rsrc_mem(&rominfo, ent, 8);
454 pr_debug(" ROM: [ 0x%08lx 0x%08lx ]\n",
455 rominfo[0], rominfo[1]);
456 nubus_proc_add_rsrc_mem(procdir, ent, 8);
457 break;
458 }
459 default:
460 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
461 ent->type, ent->data);
462 nubus_proc_add_rsrc_mem(procdir, ent, 0);
463 }
464 return 0;
465}
466
467static int __init nubus_get_private_resource(struct nubus_rsrc *fres,
468 struct proc_dir_entry *procdir,
469 const struct nubus_dirent *ent)
470{
471 switch (fres->category) {
472 case NUBUS_CAT_DISPLAY:
473 nubus_get_display_resource(fres, procdir, ent);
474 break;
475 case NUBUS_CAT_NETWORK:
476 nubus_get_network_resource(fres, procdir, ent);
477 break;
478 case NUBUS_CAT_CPU:
479 nubus_get_cpu_resource(fres, procdir, ent);
480 break;
481 default:
482 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
483 ent->type, ent->data);
484 nubus_proc_add_rsrc_mem(procdir, ent, 0);
485 }
486 return 0;
487}
488
489static struct nubus_rsrc * __init
490nubus_get_functional_resource(struct nubus_board *board, int slot,
491 const struct nubus_dirent *parent)
492{
493 struct nubus_dir dir;
494 struct nubus_dirent ent;
495 struct nubus_rsrc *fres;
496
497 pr_debug(" Functional resource 0x%02x:\n", parent->type);
498 nubus_get_subdir(parent, &dir);
499 dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
500
501
502 fres = kzalloc(sizeof(*fres), GFP_ATOMIC);
503 if (!fres)
504 return NULL;
505 fres->resid = parent->type;
506 fres->directory = dir.base;
507 fres->board = board;
508
509 while (nubus_readdir(&dir, &ent) != -1) {
510 switch (ent.type) {
511 case NUBUS_RESID_TYPE:
512 {
513 unsigned short nbtdata[4];
514
515 nubus_get_rsrc_mem(nbtdata, &ent, 8);
516 fres->category = nbtdata[0];
517 fres->type = nbtdata[1];
518 fres->dr_sw = nbtdata[2];
519 fres->dr_hw = nbtdata[3];
520 pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
521 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
522 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
523 break;
524 }
525 case NUBUS_RESID_NAME:
526 {
527 char name[64];
528 unsigned int len;
529
530 len = nubus_get_rsrc_str(name, &ent, sizeof(name));
531 pr_debug(" name: %s\n", name);
532 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
533 break;
534 }
535 case NUBUS_RESID_DRVRDIR:
536 {
537
538
539 pr_debug(" driver directory offset: 0x%06x\n",
540 ent.data);
541 nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
542 break;
543 }
544 case NUBUS_RESID_MINOR_BASEOS:
545 {
546
547
548
549 u32 base_offset;
550
551 nubus_get_rsrc_mem(&base_offset, &ent, 4);
552 pr_debug(" memory offset: 0x%08x\n", base_offset);
553 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
554 break;
555 }
556 case NUBUS_RESID_MINOR_LENGTH:
557 {
558
559 u32 length;
560
561 nubus_get_rsrc_mem(&length, &ent, 4);
562 pr_debug(" memory length: 0x%08x\n", length);
563 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
564 break;
565 }
566 case NUBUS_RESID_FLAGS:
567 pr_debug(" flags: 0x%06x\n", ent.data);
568 nubus_proc_add_rsrc(dir.procdir, &ent);
569 break;
570 case NUBUS_RESID_HWDEVID:
571 pr_debug(" hwdevid: 0x%06x\n", ent.data);
572 nubus_proc_add_rsrc(dir.procdir, &ent);
573 break;
574 default:
575
576
577 nubus_get_private_resource(fres, dir.procdir, &ent);
578 }
579 }
580
581 return fres;
582}
583
584
585static int __init nubus_get_icon(struct nubus_board *board,
586 struct proc_dir_entry *procdir,
587 const struct nubus_dirent *ent)
588{
589
590 u32 icon[32];
591 int i;
592
593 nubus_get_rsrc_mem(&icon, ent, 128);
594 pr_debug(" icon:\n");
595 for (i = 0; i < 8; i++)
596 pr_debug(" %08x %08x %08x %08x\n",
597 icon[i * 4 + 0], icon[i * 4 + 1],
598 icon[i * 4 + 2], icon[i * 4 + 3]);
599 nubus_proc_add_rsrc_mem(procdir, ent, 128);
600
601 return 0;
602}
603
604static int __init nubus_get_vendorinfo(struct nubus_board *board,
605 struct proc_dir_entry *procdir,
606 const struct nubus_dirent *parent)
607{
608 struct nubus_dir dir;
609 struct nubus_dirent ent;
610 static char *vendor_fields[6] = { "ID", "serial", "revision",
611 "part", "date", "unknown field" };
612
613 pr_debug(" vendor info:\n");
614 nubus_get_subdir(parent, &dir);
615 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
616
617 while (nubus_readdir(&dir, &ent) != -1) {
618 char name[64];
619 unsigned int len;
620
621
622 len = nubus_get_rsrc_str(name, &ent, sizeof(name));
623 if (ent.type < 1 || ent.type > 5)
624 ent.type = 5;
625 pr_debug(" %s: %s\n", vendor_fields[ent.type - 1], name);
626 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
627 }
628 return 0;
629}
630
631static int __init nubus_get_board_resource(struct nubus_board *board, int slot,
632 const struct nubus_dirent *parent)
633{
634 struct nubus_dir dir;
635 struct nubus_dirent ent;
636
637 pr_debug(" Board resource 0x%02x:\n", parent->type);
638 nubus_get_subdir(parent, &dir);
639 dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
640
641 while (nubus_readdir(&dir, &ent) != -1) {
642 switch (ent.type) {
643 case NUBUS_RESID_TYPE:
644 {
645 unsigned short nbtdata[4];
646
647
648
649 nubus_get_rsrc_mem(nbtdata, &ent, 8);
650 pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
651 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
652 if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
653 nbtdata[2] != 0 || nbtdata[3] != 0)
654 pr_err("Slot %X: sResource is not a board resource!\n",
655 slot);
656 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
657 break;
658 }
659 case NUBUS_RESID_NAME:
660 {
661 unsigned int len;
662
663 len = nubus_get_rsrc_str(board->name, &ent,
664 sizeof(board->name));
665 pr_debug(" name: %s\n", board->name);
666 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
667 break;
668 }
669 case NUBUS_RESID_ICON:
670 nubus_get_icon(board, dir.procdir, &ent);
671 break;
672 case NUBUS_RESID_BOARDID:
673 pr_debug(" board id: 0x%x\n", ent.data);
674 nubus_proc_add_rsrc(dir.procdir, &ent);
675 break;
676 case NUBUS_RESID_PRIMARYINIT:
677 pr_debug(" primary init offset: 0x%06x\n", ent.data);
678 nubus_proc_add_rsrc(dir.procdir, &ent);
679 break;
680 case NUBUS_RESID_VENDORINFO:
681 nubus_get_vendorinfo(board, dir.procdir, &ent);
682 break;
683 case NUBUS_RESID_FLAGS:
684 pr_debug(" flags: 0x%06x\n", ent.data);
685 nubus_proc_add_rsrc(dir.procdir, &ent);
686 break;
687 case NUBUS_RESID_HWDEVID:
688 pr_debug(" hwdevid: 0x%06x\n", ent.data);
689 nubus_proc_add_rsrc(dir.procdir, &ent);
690 break;
691 case NUBUS_RESID_SECONDINIT:
692 pr_debug(" secondary init offset: 0x%06x\n",
693 ent.data);
694 nubus_proc_add_rsrc(dir.procdir, &ent);
695 break;
696
697 case NUBUS_RESID_VIDNAMES:
698 pr_debug(" vidnames directory offset: 0x%06x\n",
699 ent.data);
700 nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
701 break;
702
703 case NUBUS_RESID_VIDMODES:
704 pr_debug(" video mode parameter directory offset: 0x%06x\n",
705 ent.data);
706 nubus_proc_add_rsrc(dir.procdir, &ent);
707 break;
708 default:
709 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
710 ent.type, ent.data);
711 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
712 }
713 }
714 return 0;
715}
716
717static void __init nubus_add_board(int slot, int bytelanes)
718{
719 struct nubus_board *board;
720 unsigned char *rp;
721 unsigned long dpat;
722 struct nubus_dir dir;
723 struct nubus_dirent ent;
724 int prev_resid = -1;
725
726
727 rp = nubus_rom_addr(slot);
728 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
729
730
731 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
732 return;
733 board->fblock = rp;
734
735
736 pr_debug("Slot %X, format block at 0x%p:\n", slot, rp);
737 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
738 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
739 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
740 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
741 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
742 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
743 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
744 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
745 rp = board->fblock;
746
747 board->slot = slot;
748 board->slot_addr = (unsigned long)nubus_slot_addr(slot);
749 board->doffset = nubus_get_rom(&rp, 4, bytelanes);
750
751
752
753
754
755
756 board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
757 board->crc = nubus_get_rom(&rp, 4, bytelanes);
758 board->rev = nubus_get_rom(&rp, 1, bytelanes);
759 board->format = nubus_get_rom(&rp, 1, bytelanes);
760 board->lanes = bytelanes;
761
762
763 if (!(board->doffset & 0x00FF0000))
764 pr_warn("Slot %X: Dodgy doffset!\n", slot);
765 dpat = nubus_get_rom(&rp, 4, bytelanes);
766 if (dpat != NUBUS_TEST_PATTERN)
767 pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat);
768
769
770
771
772
773
774
775
776
777 board->directory = board->fblock;
778 nubus_move(&board->directory, nubus_expand32(board->doffset),
779 board->lanes);
780
781 nubus_get_root_dir(board, &dir);
782
783
784 pr_debug("Slot %X resources:\n", slot);
785
786
787
788
789
790
791
792 if (nubus_readdir(&dir, &ent) == -1) {
793
794 pr_err("Slot %X: Board resource not found!\n", slot);
795 kfree(board);
796 return;
797 }
798
799 if (ent.type < 1 || ent.type > 127)
800 pr_warn("Slot %X: Board resource ID is invalid!\n", slot);
801
802 board->procdir = nubus_proc_add_board(board);
803
804 nubus_get_board_resource(board, slot, &ent);
805
806 while (nubus_readdir(&dir, &ent) != -1) {
807 struct nubus_rsrc *fres;
808
809 fres = nubus_get_functional_resource(board, slot, &ent);
810 if (fres == NULL)
811 continue;
812
813
814
815
816 if (fres->resid <= prev_resid) {
817 kfree(fres);
818 continue;
819 }
820 prev_resid = fres->resid;
821
822 list_add_tail(&fres->list, &nubus_func_rsrcs);
823 }
824
825 if (nubus_device_register(board))
826 put_device(&board->dev);
827}
828
829static void __init nubus_probe_slot(int slot)
830{
831 unsigned char dp;
832 unsigned char *rp;
833 int i;
834
835 rp = nubus_rom_addr(slot);
836 for (i = 4; i; i--) {
837 rp--;
838 if (!hwreg_present(rp))
839 continue;
840
841 dp = *rp;
842
843
844
845
846 if ((((dp >> 4) ^ dp) & 0x0F) != 0x0F)
847 continue;
848
849
850 if (not_useful(rp, dp))
851 continue;
852
853
854 nubus_add_board(slot, dp);
855
856 return;
857 }
858}
859
860static void __init nubus_scan_bus(void)
861{
862 int slot;
863
864 pr_info("NuBus: Scanning NuBus slots.\n");
865 for (slot = 9; slot < 15; slot++) {
866 nubus_probe_slot(slot);
867 }
868}
869
870static int __init nubus_init(void)
871{
872 int err;
873
874 if (!MACH_IS_MAC)
875 return 0;
876
877 nubus_proc_init();
878 err = nubus_bus_register();
879 if (err)
880 return err;
881 nubus_scan_bus();
882 return 0;
883}
884
885subsys_initcall(nubus_init);
886