Loading...
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Macintosh Nubus Interface Code
4 *
5 * Originally by Alan Cox
6 *
7 * Mostly rewritten by David Huggins-Daines, C. Scott Ananian,
8 * and others.
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/* Constants */
25
26/* This is, of course, the size in bytelanes, rather than the size in
27 actual bytes */
28#define FORMAT_BLOCK_SIZE 20
29#define ROM_DIR_OFFSET 0x24
30
31#define NUBUS_TEST_PATTERN 0x5A932BC7
32
33/* Globals */
34
35LIST_HEAD(nubus_func_rsrcs);
36
37/* Meaning of "bytelanes":
38
39 The card ROM may appear on any or all bytes of each long word in
40 NuBus memory. The low 4 bits of the "map" value found in the
41 format block (at the top of the slot address space, as well as at
42 the top of the MacOS ROM) tells us which bytelanes, i.e. which byte
43 offsets within each longword, are valid. Thus:
44
45 A map of 0x0f, as found in the MacOS ROM, means that all bytelanes
46 are valid.
47
48 A map of 0xf0 means that no bytelanes are valid (We pray that we
49 will never encounter this, but stranger things have happened)
50
51 A map of 0xe1 means that only the MSB of each long word is actually
52 part of the card ROM. (We hope to never encounter NuBus on a
53 little-endian machine. Again, stranger things have happened)
54
55 A map of 0x78 means that only the LSB of each long word is valid.
56
57 Etcetera, etcetera. Hopefully this clears up some confusion over
58 what the following code actually does. */
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 /* This will hold the result */
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/* Now, functions to read the sResource tree */
127
128/* Each sResource entry consists of a 1-byte ID and a 3-byte data
129 field. If that data field contains an offset, then obviously we
130 have to expand it from a 24-bit signed number to a 32-bit signed
131 number. */
132
133static inline long nubus_expand32(long foo)
134{
135 if (foo & 0x00800000) /* 24bit negative */
136 foo |= 0xFF000000;
137 return foo;
138}
139
140static inline void *nubus_rom_addr(int slot)
141{
142 /*
143 * Returns the first byte after the card. We then walk
144 * backwards to get the lane register and the config
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 /* Essentially, just step over the bytelanes using whatever
154 offset we might have found */
155 nubus_move(&p, nubus_expand32(nd->data), nd->mask);
156 /* And return the value */
157 return p;
158}
159
160/* These two are for pulling resource data blocks (i.e. stuff that's
161 pointed to with offsets) out of the card ROM. */
162
163void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
164 unsigned int len)
165{
166 unsigned char *t = 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 /* If possible, write out full buffers */
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 /* If not, write out individual bytes */
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/* This is a slyly renamed version of the above */
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 /* Now dereference it (the first directory is always the board
249 directory) */
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 /* Do this first, otherwise nubus_rewind & co are off by 4 */
276 ent->base = nd->ptr;
277
278 /* This moves nd->ptr forward */
279 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
280
281 /* EOL marker, as per the Apple docs */
282 if ((resid & 0xff000000) == 0xff000000) {
283 /* Mark it as done */
284 nd->done = 1;
285 return -1;
286 }
287
288 /* First byte is the resource ID */
289 ent->type = resid >> 24;
290 /* Low 3 bytes might contain data (or might not) */
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/* Driver interface functions, more or less like in pci.c */
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/* Initialization functions - decide which slots contain stuff worth
335 looking at, and print out lots and lots of information from the
336 resource blocks. */
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: /* mVidParams */
371 case 2: /* mTable */
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 /* Actually we should probably panic if this fails */
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 /* MacOS driver. If we were NetBSD we might
538 use this :-) */
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 /* We will need this in order to support
547 multiple framebuffers. It might be handy
548 for Ethernet as well */
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 /* Ditto */
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 /* Local/Private resources have their own
576 function */
577 nubus_get_private_resource(fres, dir.procdir, &ent);
578 }
579 }
580
581 return fres;
582}
583
584/* This is *really* cool. */
585static int __init nubus_get_icon(struct nubus_board *board,
586 struct proc_dir_entry *procdir,
587 const struct nubus_dirent *ent)
588{
589 /* Should be 32x32 if my memory serves me correctly */
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 /* These are all strings, we think */
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 /* This type is always the same, and is not
647 useful except insofar as it tells us that
648 we really are looking at a board resource. */
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 /* WTF isn't this in the functional resources? */
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 /* Same goes for this */
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 /* Move to the start of the format block */
727 rp = nubus_rom_addr(slot);
728 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
729
730 /* Actually we should probably panic if this fails */
731 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
732 return;
733 board->fblock = rp;
734
735 /* Dump the format block for debugging purposes */
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 /* rom_length is *supposed* to be the total length of the
751 * ROM. In practice it is the "amount of ROM used to compute
752 * the CRC." So some jokers decide to set it to zero and
753 * set the crc to zero so they don't have to do any math.
754 * See the Performa 460 ROM, for example. Those Apple "engineers".
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 /* Directory offset should be small and negative... */
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 * I wonder how the CRC is meant to work -
771 * any takers ?
772 * CSA: According to MAC docs, not all cards pass the CRC anyway,
773 * since the initial Macintosh ROM releases skipped the check.
774 */
775
776 /* Set up the directory pointer */
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 /* We're ready to rock */
784 pr_debug("Slot %X resources:\n", slot);
785
786 /* Each slot should have one board resource and any number of
787 * functional resources. So we'll fill in some fields in the
788 * struct nubus_board from the board resource, then walk down
789 * the list of functional resources, spinning out a nubus_rsrc
790 * for each of them.
791 */
792 if (nubus_readdir(&dir, &ent) == -1) {
793 /* We can't have this! */
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 /* Resources should appear in ascending ID order. This sanity
814 * check prevents duplicate resource IDs.
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 /* The last byte of the format block consists of two
844 nybbles which are "mirror images" of each other.
845 These show us the valid bytelanes */
846 if ((((dp >> 4) ^ dp) & 0x0F) != 0x0F)
847 continue;
848 /* Check that this value is actually *on* one of the
849 bytelanes it claims are valid! */
850 if (not_useful(rp, dp))
851 continue;
852
853 /* Looks promising. Let's put it on the list. */
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_parent_device_register();
879 if (err)
880 return err;
881 nubus_scan_bus();
882 return 0;
883}
884
885subsys_initcall(nubus_init);
1/*
2 * Macintosh Nubus Interface Code
3 *
4 * Originally by Alan Cox
5 *
6 * Mostly rewritten by David Huggins-Daines, C. Scott Ananian,
7 * and others.
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 <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/* Constants */
30
31/* This is, of course, the size in bytelanes, rather than the size in
32 actual bytes */
33#define FORMAT_BLOCK_SIZE 20
34#define ROM_DIR_OFFSET 0x24
35
36#define NUBUS_TEST_PATTERN 0x5A932BC7
37
38/* Define this if you like to live dangerously - it is known not to
39 work on pretty much every machine except the Quadra 630 and the LC
40 III. */
41#undef I_WANT_TO_PROBE_SLOT_ZERO
42
43/* This sometimes helps combat failure to boot */
44#undef TRY_TO_DODGE_WSOD
45
46/* Globals */
47
48struct nubus_dev* nubus_devices;
49struct nubus_board* nubus_boards;
50
51/* Meaning of "bytelanes":
52
53 The card ROM may appear on any or all bytes of each long word in
54 NuBus memory. The low 4 bits of the "map" value found in the
55 format block (at the top of the slot address space, as well as at
56 the top of the MacOS ROM) tells us which bytelanes, i.e. which byte
57 offsets within each longword, are valid. Thus:
58
59 A map of 0x0f, as found in the MacOS ROM, means that all bytelanes
60 are valid.
61
62 A map of 0xf0 means that no bytelanes are valid (We pray that we
63 will never encounter this, but stranger things have happened)
64
65 A map of 0xe1 means that only the MSB of each long word is actually
66 part of the card ROM. (We hope to never encounter NuBus on a
67 little-endian machine. Again, stranger things have happened)
68
69 A map of 0x78 means that only the LSB of each long word is valid.
70
71 Etcetera, etcetera. Hopefully this clears up some confusion over
72 what the following code actually does. */
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 /* This will hold the result */
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 /* Sanity check */
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/* Now, functions to read the sResource tree */
144
145/* Each sResource entry consists of a 1-byte ID and a 3-byte data
146 field. If that data field contains an offset, then obviously we
147 have to expand it from a 24-bit signed number to a 32-bit signed
148 number. */
149
150static inline long nubus_expand32(long foo)
151{
152 if(foo & 0x00800000) /* 24bit negative */
153 foo |= 0xFF000000;
154 return foo;
155}
156
157static inline void *nubus_rom_addr(int slot)
158{
159 /*
160 * Returns the first byte after the card. We then walk
161 * backwards to get the lane register and the config
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 /* Essentially, just step over the bytelanes using whatever
170 offset we might have found */
171 nubus_move(&p, nubus_expand32(nd->data), nd->mask);
172 /* And return the value */
173 return p;
174}
175
176/* These two are for pulling resource data blocks (i.e. stuff that's
177 pointed to with offsets) out of the card ROM. */
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/* This is a slyly renamed version of the above */
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 /* Now dereference it (the first directory is always the board
238 directory) */
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 /* Do this first, otherwise nubus_rewind & co are off by 4 */
264 ent->base = nd->ptr;
265
266 /* This moves nd->ptr forward */
267 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
268
269 /* EOL marker, as per the Apple docs */
270 if((resid&0xff000000) == 0xff000000)
271 {
272 /* Mark it as done */
273 nd->done = 1;
274 return -1;
275 }
276
277 /* First byte is the resource ID */
278 ent->type = resid >> 24;
279 /* Low 3 bytes might contain data (or might not) */
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/* Driver interface functions, more or less like in pci.c */
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/* Initialization functions - decide which slots contain stuff worth
364 looking at, and print out lots and lots of information from the
365 resource blocks. */
366
367/* FIXME: A lot of this stuff will eventually be useful after
368 initialization, for intelligently probing Ethernet and video chips,
369 among other things. The rest of it should go in the /proc code.
370 For now, we just use it to give verbose boot logs. */
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 /* Apple seems to have botched the ROM on the IIx */
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 /* Actually we should probably panic if this fails */
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 /* MacOS driver. If we were NetBSD we might
513 use this :-) */
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 /* We will need this in order to support
525 multiple framebuffers. It might be handy
526 for Ethernet as well */
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 /* Ditto */
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 /* Local/Private resources have their own
547 function */
548 nubus_show_private_resource(dev, &ent);
549 }
550 }
551
552 return dev;
553}
554
555/* This is cool. */
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 /* FIXME: obviously we want to put this in a header file soon */
562 struct vidmode {
563 u32 size;
564 /* Don't know what this is yet */
565 u16 id;
566 /* Longest one I've seen so far is 26 characters */
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 /* First get the length */
582 nubus_get_rsrc_mem(&size, &ent, 4);
583
584 /* Now clobber the whole thing */
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/* This is *really* cool. */
596static int __init nubus_get_icon(struct nubus_board* board,
597 const struct nubus_dirent* ent)
598{
599 /* Should be 32x32 if my memory serves me correctly */
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 /* We should actually plot these somewhere in the framebuffer
607 init. This is just to demonstrate that they do, in fact,
608 exist */
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 /* These are all strings, we think */
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 /* This type is always the same, and is not
669 useful except insofar as it tells us that
670 we really are looking at a board resource. */
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 /* WTF isn't this in the functional resources? */
706 case NUBUS_RESID_VIDNAMES:
707 nubus_get_vidnames(board, &ent);
708 break;
709 /* Same goes for this */
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/* Attempt to bypass the somewhat non-obvious arrangement of
723 sResources in the motherboard ROM */
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 /* Check for the extra directory just under the format block */
732 rp = board->fblock;
733 nubus_rewind(&rp, 4, board->lanes);
734 if (nubus_get_rom(&rp, 4, board->lanes) != NUBUS_TEST_PATTERN) {
735 /* OK, the ROM was telling the truth */
736 board->directory = board->fblock;
737 nubus_move(&board->directory,
738 nubus_expand32(board->doffset),
739 board->lanes);
740 return;
741 }
742
743 /* On "slot zero", you have to walk down a few more
744 directories to get to the equivalent of a real card's root
745 directory. We don't know what they were smoking when they
746 came up with this. */
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 /* This one points to an "Unknown Macintosh" directory */
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 /* This one takes us to where we want to go. */
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 /* Resource ID 01, also an "Unknown Macintosh" */
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 /* FIXME: the first one is *not* always the right one. We
773 suspect this has something to do with the ROM revision.
774 "The HORROR ROM" (LC-series) uses 0x7e, while "The HORROR
775 Continues" (Q630) uses 0x7b. The DAFB Macs evidently use
776 something else. Please run "Slots" on your Mac (see
777 include/linux/nubus.h for where to get this program) and
778 tell us where the 'SiDirPtr' for Slot 0 is. If you feel
779 brave, you should also use MacsBug to walk down the ROM
780 directories like this function does and try to find the
781 path to that address... */
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 /* Bwahahahaha... */
788 nubus_get_subdir(&ent, &dir);
789 board->directory = dir.base;
790 return;
791
792 /* Even more evil laughter... */
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/* Add a board (might be many devices) to the list */
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 /* Move to the start of the format block */
811 rp = nubus_rom_addr(slot);
812 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
813
814 /* Actually we should probably panic if this fails */
815 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
816 return NULL;
817 board->fblock = rp;
818
819 /* Dump the format block for debugging purposes */
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 /* rom_length is *supposed* to be the total length of the
839 * ROM. In practice it is the "amount of ROM used to compute
840 * the CRC." So some jokers decide to set it to zero and
841 * set the crc to zero so they don't have to do any math.
842 * See the Performa 460 ROM, for example. Those Apple "engineers".
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 /* Directory offset should be small and negative... */
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 * I wonder how the CRC is meant to work -
859 * any takers ?
860 * CSA: According to MAC docs, not all cards pass the CRC anyway,
861 * since the initial Macintosh ROM releases skipped the check.
862 */
863
864 /* Attempt to work around slot zero weirdness */
865 nubus_find_rom_dir(board);
866 nubus_get_root_dir(board, &dir);
867
868 /* We're ready to rock */
869 printk(KERN_INFO "Slot %X:\n", slot);
870
871 /* Each slot should have one board resource and any number of
872 functional resources. So we'll fill in some fields in the
873 struct nubus_board from the board resource, then walk down
874 the list of functional resources, spinning out a nubus_dev
875 for each of them. */
876 if (nubus_readdir(&dir, &ent) == -1) {
877 /* We can't have this! */
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 /* Aaaarrrrgghh! The LC III motherboard has *two* board
886 resources. I have no idea WTF to do about this. */
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 /* We zeroed this out above */
896 if (board->first_dev == NULL)
897 board->first_dev = dev;
898
899 /* Put it on the global NuBus device chain. Keep entries in order. */
900 for (devp=&nubus_devices; *devp!=NULL; devp=&((*devp)->next))
901 /* spin */;
902 *devp = dev;
903 dev->next = NULL;
904 }
905
906 /* Put it on the global NuBus board chain. Keep entries in order. */
907 for (boardp=&nubus_boards; *boardp!=NULL; boardp=&((*boardp)->next))
908 /* spin */;
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 /* The last byte of the format block consists of two
941 nybbles which are "mirror images" of each other.
942 These show us the valid bytelanes */
943 if ((((dp>>4) ^ dp) & 0x0F) != 0x0F)
944 continue;
945 /* Check that this value is actually *on* one of the
946 bytelanes it claims are valid! */
947 if ((dp & 0x0F) >= (1<<i))
948 continue;
949
950 /* Looks promising. Let's put it on the list. */
951 nubus_add_board(slot, dp);
952
953 return;
954 }
955}
956
957#if defined(CONFIG_PROC_FS)
958
959/* /proc/nubus stuff */
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 /* Walk the list of NuBus boards */
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 /* This might not work on your machine */
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 /* Initialize the NuBus interrupts */
1026 if (oss_present) {
1027 oss_nubus_init();
1028 } else {
1029 via_nubus_init();
1030 }
1031
1032#ifdef TRY_TO_DODGE_WSOD
1033 /* Rogue Ethernet interrupts can kill the machine if we don't
1034 do this. Obviously this is bogus. Hopefully the local VIA
1035 gurus can fix the real cause of the problem. */
1036 mdelay(1000);
1037#endif
1038
1039 /* And probe */
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);