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// 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
35/* The "nubus.populate_procfs" parameter makes slot resources available in
36 * procfs. It's deprecated and disabled by default because procfs is no longer
37 * thought to be suitable for that and some board ROMs make it too expensive.
38 */
39bool nubus_populate_procfs;
40module_param_named(populate_procfs, nubus_populate_procfs, bool, 0);
41
42LIST_HEAD(nubus_func_rsrcs);
43
44/* Meaning of "bytelanes":
45
46 The card ROM may appear on any or all bytes of each long word in
47 NuBus memory. The low 4 bits of the "map" value found in the
48 format block (at the top of the slot address space, as well as at
49 the top of the MacOS ROM) tells us which bytelanes, i.e. which byte
50 offsets within each longword, are valid. Thus:
51
52 A map of 0x0f, as found in the MacOS ROM, means that all bytelanes
53 are valid.
54
55 A map of 0xf0 means that no bytelanes are valid (We pray that we
56 will never encounter this, but stranger things have happened)
57
58 A map of 0xe1 means that only the MSB of each long word is actually
59 part of the card ROM. (We hope to never encounter NuBus on a
60 little-endian machine. Again, stranger things have happened)
61
62 A map of 0x78 means that only the LSB of each long word is valid.
63
64 Etcetera, etcetera. Hopefully this clears up some confusion over
65 what the following code actually does. */
66
67static inline int not_useful(void *p, int map)
68{
69 unsigned long pv = (unsigned long)p;
70
71 pv &= 3;
72 if (map & (1 << pv))
73 return 0;
74 return 1;
75}
76
77static unsigned long nubus_get_rom(unsigned char **ptr, int len, int map)
78{
79 /* This will hold the result */
80 unsigned long v = 0;
81 unsigned char *p = *ptr;
82
83 while (len) {
84 v <<= 8;
85 while (not_useful(p, map))
86 p++;
87 v |= *p++;
88 len--;
89 }
90 *ptr = p;
91 return v;
92}
93
94static void nubus_rewind(unsigned char **ptr, int len, int map)
95{
96 unsigned char *p = *ptr;
97
98 while (len) {
99 do {
100 p--;
101 } while (not_useful(p, map));
102 len--;
103 }
104 *ptr = p;
105}
106
107static void nubus_advance(unsigned char **ptr, int len, int map)
108{
109 unsigned char *p = *ptr;
110
111 while (len) {
112 while (not_useful(p, map))
113 p++;
114 p++;
115 len--;
116 }
117 *ptr = p;
118}
119
120static void nubus_move(unsigned char **ptr, int len, int map)
121{
122 unsigned long slot_space = (unsigned long)*ptr & 0xFF000000;
123
124 if (len > 0)
125 nubus_advance(ptr, len, map);
126 else if (len < 0)
127 nubus_rewind(ptr, -len, map);
128
129 if (((unsigned long)*ptr & 0xFF000000) != slot_space)
130 pr_err("%s: moved out of slot address space!\n", __func__);
131}
132
133/* Now, functions to read the sResource tree */
134
135/* Each sResource entry consists of a 1-byte ID and a 3-byte data
136 field. If that data field contains an offset, then obviously we
137 have to expand it from a 24-bit signed number to a 32-bit signed
138 number. */
139
140static inline long nubus_expand32(long foo)
141{
142 if (foo & 0x00800000) /* 24bit negative */
143 foo |= 0xFF000000;
144 return foo;
145}
146
147static inline void *nubus_rom_addr(int slot)
148{
149 /*
150 * Returns the first byte after the card. We then walk
151 * backwards to get the lane register and the config
152 */
153 return (void *)(0xF1000000 + (slot << 24));
154}
155
156unsigned char *nubus_dirptr(const struct nubus_dirent *nd)
157{
158 unsigned char *p = nd->base;
159
160 /* Essentially, just step over the bytelanes using whatever
161 offset we might have found */
162 nubus_move(&p, nubus_expand32(nd->data), nd->mask);
163 /* And return the value */
164 return p;
165}
166
167/* These two are for pulling resource data blocks (i.e. stuff that's
168 pointed to with offsets) out of the card ROM. */
169
170void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
171 unsigned int len)
172{
173 unsigned char *t = dest;
174 unsigned char *p = nubus_dirptr(dirent);
175
176 while (len) {
177 *t++ = nubus_get_rom(&p, 1, dirent->mask);
178 len--;
179 }
180}
181EXPORT_SYMBOL(nubus_get_rsrc_mem);
182
183unsigned int nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
184 unsigned int len)
185{
186 char *t = dest;
187 unsigned char *p = nubus_dirptr(dirent);
188
189 while (len > 1) {
190 unsigned char c = nubus_get_rom(&p, 1, dirent->mask);
191
192 if (!c)
193 break;
194 *t++ = c;
195 len--;
196 }
197 if (len > 0)
198 *t = '\0';
199 return t - dest;
200}
201EXPORT_SYMBOL(nubus_get_rsrc_str);
202
203void nubus_seq_write_rsrc_mem(struct seq_file *m,
204 const struct nubus_dirent *dirent,
205 unsigned int len)
206{
207 unsigned long buf[32];
208 unsigned int buf_size = sizeof(buf);
209 unsigned char *p = nubus_dirptr(dirent);
210
211 /* If possible, write out full buffers */
212 while (len >= buf_size) {
213 unsigned int i;
214
215 for (i = 0; i < ARRAY_SIZE(buf); i++)
216 buf[i] = nubus_get_rom(&p, sizeof(buf[0]),
217 dirent->mask);
218 seq_write(m, buf, buf_size);
219 len -= buf_size;
220 }
221 /* If not, write out individual bytes */
222 while (len--)
223 seq_putc(m, nubus_get_rom(&p, 1, dirent->mask));
224}
225
226int nubus_get_root_dir(const struct nubus_board *board,
227 struct nubus_dir *dir)
228{
229 dir->ptr = dir->base = board->directory;
230 dir->done = 0;
231 dir->mask = board->lanes;
232 return 0;
233}
234EXPORT_SYMBOL(nubus_get_root_dir);
235
236/* This is a slyly renamed version of the above */
237int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir)
238{
239 dir->ptr = dir->base = fres->directory;
240 dir->done = 0;
241 dir->mask = fres->board->lanes;
242 return 0;
243}
244EXPORT_SYMBOL(nubus_get_func_dir);
245
246int nubus_get_board_dir(const struct nubus_board *board,
247 struct nubus_dir *dir)
248{
249 struct nubus_dirent ent;
250
251 dir->ptr = dir->base = board->directory;
252 dir->done = 0;
253 dir->mask = board->lanes;
254
255 /* Now dereference it (the first directory is always the board
256 directory) */
257 if (nubus_readdir(dir, &ent) == -1)
258 return -1;
259 if (nubus_get_subdir(&ent, dir) == -1)
260 return -1;
261 return 0;
262}
263EXPORT_SYMBOL(nubus_get_board_dir);
264
265int nubus_get_subdir(const struct nubus_dirent *ent,
266 struct nubus_dir *dir)
267{
268 dir->ptr = dir->base = nubus_dirptr(ent);
269 dir->done = 0;
270 dir->mask = ent->mask;
271 return 0;
272}
273EXPORT_SYMBOL(nubus_get_subdir);
274
275int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
276{
277 u32 resid;
278
279 if (nd->done)
280 return -1;
281
282 /* Do this first, otherwise nubus_rewind & co are off by 4 */
283 ent->base = nd->ptr;
284
285 /* This moves nd->ptr forward */
286 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
287
288 /* EOL marker, as per the Apple docs */
289 if ((resid & 0xff000000) == 0xff000000) {
290 /* Mark it as done */
291 nd->done = 1;
292 return -1;
293 }
294
295 /* First byte is the resource ID */
296 ent->type = resid >> 24;
297 /* Low 3 bytes might contain data (or might not) */
298 ent->data = resid & 0xffffff;
299 ent->mask = nd->mask;
300 return 0;
301}
302EXPORT_SYMBOL(nubus_readdir);
303
304int nubus_rewinddir(struct nubus_dir *dir)
305{
306 dir->ptr = dir->base;
307 dir->done = 0;
308 return 0;
309}
310EXPORT_SYMBOL(nubus_rewinddir);
311
312/* Driver interface functions, more or less like in pci.c */
313
314struct nubus_rsrc *nubus_first_rsrc_or_null(void)
315{
316 return list_first_entry_or_null(&nubus_func_rsrcs, struct nubus_rsrc,
317 list);
318}
319EXPORT_SYMBOL(nubus_first_rsrc_or_null);
320
321struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from)
322{
323 if (list_is_last(&from->list, &nubus_func_rsrcs))
324 return NULL;
325 return list_next_entry(from, list);
326}
327EXPORT_SYMBOL(nubus_next_rsrc_or_null);
328
329int
330nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type,
331 struct nubus_dirent *ent)
332{
333 while (nubus_readdir(dir, ent) != -1) {
334 if (ent->type == rsrc_type)
335 return 0;
336 }
337 return -1;
338}
339EXPORT_SYMBOL(nubus_find_rsrc);
340
341/* Initialization functions - decide which slots contain stuff worth
342 looking at, and print out lots and lots of information from the
343 resource blocks. */
344
345static int __init nubus_get_block_rsrc_dir(struct nubus_board *board,
346 struct proc_dir_entry *procdir,
347 const struct nubus_dirent *parent)
348{
349 struct nubus_dir dir;
350 struct nubus_dirent ent;
351
352 nubus_get_subdir(parent, &dir);
353 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
354
355 while (nubus_readdir(&dir, &ent) != -1) {
356 u32 size;
357
358 nubus_get_rsrc_mem(&size, &ent, 4);
359 pr_debug(" block (0x%x), size %d\n", ent.type, size);
360 nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
361 }
362 return 0;
363}
364
365static int __init nubus_get_display_vidmode(struct nubus_board *board,
366 struct proc_dir_entry *procdir,
367 const struct nubus_dirent *parent)
368{
369 struct nubus_dir dir;
370 struct nubus_dirent ent;
371
372 nubus_get_subdir(parent, &dir);
373 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
374
375 while (nubus_readdir(&dir, &ent) != -1) {
376 switch (ent.type) {
377 case 1: /* mVidParams */
378 case 2: /* mTable */
379 {
380 u32 size;
381
382 nubus_get_rsrc_mem(&size, &ent, 4);
383 pr_debug(" block (0x%x), size %d\n", ent.type,
384 size);
385 nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
386 break;
387 }
388 default:
389 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
390 ent.type, ent.data);
391 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
392 }
393 }
394 return 0;
395}
396
397static int __init nubus_get_display_resource(struct nubus_rsrc *fres,
398 struct proc_dir_entry *procdir,
399 const struct nubus_dirent *ent)
400{
401 switch (ent->type) {
402 case NUBUS_RESID_GAMMADIR:
403 pr_debug(" gamma directory offset: 0x%06x\n", ent->data);
404 nubus_get_block_rsrc_dir(fres->board, procdir, ent);
405 break;
406 case 0x0080 ... 0x0085:
407 pr_debug(" mode 0x%02x info offset: 0x%06x\n",
408 ent->type, ent->data);
409 nubus_get_display_vidmode(fres->board, procdir, ent);
410 break;
411 default:
412 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
413 ent->type, ent->data);
414 nubus_proc_add_rsrc_mem(procdir, ent, 0);
415 }
416 return 0;
417}
418
419static int __init nubus_get_network_resource(struct nubus_rsrc *fres,
420 struct proc_dir_entry *procdir,
421 const struct nubus_dirent *ent)
422{
423 switch (ent->type) {
424 case NUBUS_RESID_MAC_ADDRESS:
425 {
426 char addr[6];
427
428 nubus_get_rsrc_mem(addr, ent, 6);
429 pr_debug(" MAC address: %pM\n", addr);
430 nubus_proc_add_rsrc_mem(procdir, ent, 6);
431 break;
432 }
433 default:
434 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
435 ent->type, ent->data);
436 nubus_proc_add_rsrc_mem(procdir, ent, 0);
437 }
438 return 0;
439}
440
441static int __init nubus_get_cpu_resource(struct nubus_rsrc *fres,
442 struct proc_dir_entry *procdir,
443 const struct nubus_dirent *ent)
444{
445 switch (ent->type) {
446 case NUBUS_RESID_MEMINFO:
447 {
448 unsigned long meminfo[2];
449
450 nubus_get_rsrc_mem(&meminfo, ent, 8);
451 pr_debug(" memory: [ 0x%08lx 0x%08lx ]\n",
452 meminfo[0], meminfo[1]);
453 nubus_proc_add_rsrc_mem(procdir, ent, 8);
454 break;
455 }
456 case NUBUS_RESID_ROMINFO:
457 {
458 unsigned long rominfo[2];
459
460 nubus_get_rsrc_mem(&rominfo, ent, 8);
461 pr_debug(" ROM: [ 0x%08lx 0x%08lx ]\n",
462 rominfo[0], rominfo[1]);
463 nubus_proc_add_rsrc_mem(procdir, ent, 8);
464 break;
465 }
466 default:
467 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
468 ent->type, ent->data);
469 nubus_proc_add_rsrc_mem(procdir, ent, 0);
470 }
471 return 0;
472}
473
474static int __init nubus_get_private_resource(struct nubus_rsrc *fres,
475 struct proc_dir_entry *procdir,
476 const struct nubus_dirent *ent)
477{
478 switch (fres->category) {
479 case NUBUS_CAT_DISPLAY:
480 nubus_get_display_resource(fres, procdir, ent);
481 break;
482 case NUBUS_CAT_NETWORK:
483 nubus_get_network_resource(fres, procdir, ent);
484 break;
485 case NUBUS_CAT_CPU:
486 nubus_get_cpu_resource(fres, procdir, ent);
487 break;
488 default:
489 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
490 ent->type, ent->data);
491 nubus_proc_add_rsrc_mem(procdir, ent, 0);
492 }
493 return 0;
494}
495
496static struct nubus_rsrc * __init
497nubus_get_functional_resource(struct nubus_board *board, int slot,
498 const struct nubus_dirent *parent)
499{
500 struct nubus_dir dir;
501 struct nubus_dirent ent;
502 struct nubus_rsrc *fres;
503
504 pr_debug(" Functional resource 0x%02x:\n", parent->type);
505 nubus_get_subdir(parent, &dir);
506 dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
507
508 /* Actually we should probably panic if this fails */
509 fres = kzalloc(sizeof(*fres), GFP_ATOMIC);
510 if (!fres)
511 return NULL;
512 fres->resid = parent->type;
513 fres->directory = dir.base;
514 fres->board = board;
515
516 while (nubus_readdir(&dir, &ent) != -1) {
517 switch (ent.type) {
518 case NUBUS_RESID_TYPE:
519 {
520 unsigned short nbtdata[4];
521
522 nubus_get_rsrc_mem(nbtdata, &ent, 8);
523 fres->category = nbtdata[0];
524 fres->type = nbtdata[1];
525 fres->dr_sw = nbtdata[2];
526 fres->dr_hw = nbtdata[3];
527 pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
528 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
529 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
530 break;
531 }
532 case NUBUS_RESID_NAME:
533 {
534 char name[64];
535 unsigned int len;
536
537 len = nubus_get_rsrc_str(name, &ent, sizeof(name));
538 pr_debug(" name: %s\n", name);
539 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
540 break;
541 }
542 case NUBUS_RESID_DRVRDIR:
543 {
544 /* MacOS driver. If we were NetBSD we might
545 use this :-) */
546 pr_debug(" driver directory offset: 0x%06x\n",
547 ent.data);
548 nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
549 break;
550 }
551 case NUBUS_RESID_MINOR_BASEOS:
552 {
553 /* We will need this in order to support
554 multiple framebuffers. It might be handy
555 for Ethernet as well */
556 u32 base_offset;
557
558 nubus_get_rsrc_mem(&base_offset, &ent, 4);
559 pr_debug(" memory offset: 0x%08x\n", base_offset);
560 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
561 break;
562 }
563 case NUBUS_RESID_MINOR_LENGTH:
564 {
565 /* Ditto */
566 u32 length;
567
568 nubus_get_rsrc_mem(&length, &ent, 4);
569 pr_debug(" memory length: 0x%08x\n", length);
570 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
571 break;
572 }
573 case NUBUS_RESID_FLAGS:
574 pr_debug(" flags: 0x%06x\n", ent.data);
575 nubus_proc_add_rsrc(dir.procdir, &ent);
576 break;
577 case NUBUS_RESID_HWDEVID:
578 pr_debug(" hwdevid: 0x%06x\n", ent.data);
579 nubus_proc_add_rsrc(dir.procdir, &ent);
580 break;
581 default:
582 if (nubus_populate_procfs)
583 nubus_get_private_resource(fres, dir.procdir,
584 &ent);
585 }
586 }
587
588 return fres;
589}
590
591/* This is *really* cool. */
592static int __init nubus_get_icon(struct nubus_board *board,
593 struct proc_dir_entry *procdir,
594 const struct nubus_dirent *ent)
595{
596 /* Should be 32x32 if my memory serves me correctly */
597 u32 icon[32];
598 int i;
599
600 nubus_get_rsrc_mem(&icon, ent, 128);
601 pr_debug(" icon:\n");
602 for (i = 0; i < 8; i++)
603 pr_debug(" %08x %08x %08x %08x\n",
604 icon[i * 4 + 0], icon[i * 4 + 1],
605 icon[i * 4 + 2], icon[i * 4 + 3]);
606 nubus_proc_add_rsrc_mem(procdir, ent, 128);
607
608 return 0;
609}
610
611static int __init nubus_get_vendorinfo(struct nubus_board *board,
612 struct proc_dir_entry *procdir,
613 const struct nubus_dirent *parent)
614{
615 struct nubus_dir dir;
616 struct nubus_dirent ent;
617 static char *vendor_fields[6] = { "ID", "serial", "revision",
618 "part", "date", "unknown field" };
619
620 pr_debug(" vendor info:\n");
621 nubus_get_subdir(parent, &dir);
622 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
623
624 while (nubus_readdir(&dir, &ent) != -1) {
625 char name[64];
626 unsigned int len;
627
628 /* These are all strings, we think */
629 len = nubus_get_rsrc_str(name, &ent, sizeof(name));
630 if (ent.type < 1 || ent.type > 5)
631 ent.type = 5;
632 pr_debug(" %s: %s\n", vendor_fields[ent.type - 1], name);
633 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
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 pr_debug(" Board resource 0x%02x:\n", parent->type);
645 nubus_get_subdir(parent, &dir);
646 dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
647
648 while (nubus_readdir(&dir, &ent) != -1) {
649 switch (ent.type) {
650 case NUBUS_RESID_TYPE:
651 {
652 unsigned short nbtdata[4];
653 /* This type is always the same, and is not
654 useful except insofar as it tells us that
655 we really are looking at a board resource. */
656 nubus_get_rsrc_mem(nbtdata, &ent, 8);
657 pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
658 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
659 if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
660 nbtdata[2] != 0 || nbtdata[3] != 0)
661 pr_err("Slot %X: sResource is not a board resource!\n",
662 slot);
663 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
664 break;
665 }
666 case NUBUS_RESID_NAME:
667 {
668 unsigned int len;
669
670 len = nubus_get_rsrc_str(board->name, &ent,
671 sizeof(board->name));
672 pr_debug(" name: %s\n", board->name);
673 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
674 break;
675 }
676 case NUBUS_RESID_ICON:
677 nubus_get_icon(board, dir.procdir, &ent);
678 break;
679 case NUBUS_RESID_BOARDID:
680 pr_debug(" board id: 0x%x\n", ent.data);
681 nubus_proc_add_rsrc(dir.procdir, &ent);
682 break;
683 case NUBUS_RESID_PRIMARYINIT:
684 pr_debug(" primary init offset: 0x%06x\n", ent.data);
685 nubus_proc_add_rsrc(dir.procdir, &ent);
686 break;
687 case NUBUS_RESID_VENDORINFO:
688 nubus_get_vendorinfo(board, dir.procdir, &ent);
689 break;
690 case NUBUS_RESID_FLAGS:
691 pr_debug(" flags: 0x%06x\n", ent.data);
692 nubus_proc_add_rsrc(dir.procdir, &ent);
693 break;
694 case NUBUS_RESID_HWDEVID:
695 pr_debug(" hwdevid: 0x%06x\n", ent.data);
696 nubus_proc_add_rsrc(dir.procdir, &ent);
697 break;
698 case NUBUS_RESID_SECONDINIT:
699 pr_debug(" secondary init offset: 0x%06x\n",
700 ent.data);
701 nubus_proc_add_rsrc(dir.procdir, &ent);
702 break;
703 /* WTF isn't this in the functional resources? */
704 case NUBUS_RESID_VIDNAMES:
705 pr_debug(" vidnames directory offset: 0x%06x\n",
706 ent.data);
707 nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
708 break;
709 /* Same goes for this */
710 case NUBUS_RESID_VIDMODES:
711 pr_debug(" video mode parameter directory offset: 0x%06x\n",
712 ent.data);
713 nubus_proc_add_rsrc(dir.procdir, &ent);
714 break;
715 default:
716 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
717 ent.type, ent.data);
718 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
719 }
720 }
721 return 0;
722}
723
724static void __init nubus_add_board(int slot, int bytelanes)
725{
726 struct nubus_board *board;
727 unsigned char *rp;
728 unsigned long dpat;
729 struct nubus_dir dir;
730 struct nubus_dirent ent;
731 int prev_resid = -1;
732
733 /* Move to the start of the format block */
734 rp = nubus_rom_addr(slot);
735 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
736
737 /* Actually we should probably panic if this fails */
738 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
739 return;
740 board->fblock = rp;
741
742 /* Dump the format block for debugging purposes */
743 pr_debug("Slot %X, format block at 0x%p:\n", slot, rp);
744 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
745 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
746 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
747 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
748 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
749 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
750 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
751 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
752 rp = board->fblock;
753
754 board->slot = slot;
755 board->slot_addr = (unsigned long)nubus_slot_addr(slot);
756 board->doffset = nubus_get_rom(&rp, 4, bytelanes);
757 /* rom_length is *supposed* to be the total length of the
758 * ROM. In practice it is the "amount of ROM used to compute
759 * the CRC." So some jokers decide to set it to zero and
760 * set the crc to zero so they don't have to do any math.
761 * See the Performa 460 ROM, for example. Those Apple "engineers".
762 */
763 board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
764 board->crc = nubus_get_rom(&rp, 4, bytelanes);
765 board->rev = nubus_get_rom(&rp, 1, bytelanes);
766 board->format = nubus_get_rom(&rp, 1, bytelanes);
767 board->lanes = bytelanes;
768
769 /* Directory offset should be small and negative... */
770 if (!(board->doffset & 0x00FF0000))
771 pr_warn("Slot %X: Dodgy doffset!\n", slot);
772 dpat = nubus_get_rom(&rp, 4, bytelanes);
773 if (dpat != NUBUS_TEST_PATTERN)
774 pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat);
775
776 /*
777 * I wonder how the CRC is meant to work -
778 * any takers ?
779 * CSA: According to MAC docs, not all cards pass the CRC anyway,
780 * since the initial Macintosh ROM releases skipped the check.
781 */
782
783 /* Set up the directory pointer */
784 board->directory = board->fblock;
785 nubus_move(&board->directory, nubus_expand32(board->doffset),
786 board->lanes);
787
788 nubus_get_root_dir(board, &dir);
789
790 /* We're ready to rock */
791 pr_debug("Slot %X resources:\n", slot);
792
793 /* Each slot should have one board resource and any number of
794 * functional resources. So we'll fill in some fields in the
795 * struct nubus_board from the board resource, then walk down
796 * the list of functional resources, spinning out a nubus_rsrc
797 * for each of them.
798 */
799 if (nubus_readdir(&dir, &ent) == -1) {
800 /* We can't have this! */
801 pr_err("Slot %X: Board resource not found!\n", slot);
802 kfree(board);
803 return;
804 }
805
806 if (ent.type < 1 || ent.type > 127)
807 pr_warn("Slot %X: Board resource ID is invalid!\n", slot);
808
809 board->procdir = nubus_proc_add_board(board);
810
811 nubus_get_board_resource(board, slot, &ent);
812
813 while (nubus_readdir(&dir, &ent) != -1) {
814 struct nubus_rsrc *fres;
815
816 fres = nubus_get_functional_resource(board, slot, &ent);
817 if (fres == NULL)
818 continue;
819
820 /* Resources should appear in ascending ID order. This sanity
821 * check prevents duplicate resource IDs.
822 */
823 if (fres->resid <= prev_resid) {
824 kfree(fres);
825 continue;
826 }
827 prev_resid = fres->resid;
828
829 list_add_tail(&fres->list, &nubus_func_rsrcs);
830 }
831
832 if (nubus_device_register(board))
833 put_device(&board->dev);
834}
835
836static void __init nubus_probe_slot(int slot)
837{
838 unsigned char dp;
839 unsigned char *rp;
840 int i;
841
842 rp = nubus_rom_addr(slot);
843 for (i = 4; i; i--) {
844 rp--;
845 if (!hwreg_present(rp))
846 continue;
847
848 dp = *rp;
849
850 /* The last byte of the format block consists of two
851 nybbles which are "mirror images" of each other.
852 These show us the valid bytelanes */
853 if ((((dp >> 4) ^ dp) & 0x0F) != 0x0F)
854 continue;
855 /* Check that this value is actually *on* one of the
856 bytelanes it claims are valid! */
857 if (not_useful(rp, dp))
858 continue;
859
860 /* Looks promising. Let's put it on the list. */
861 nubus_add_board(slot, dp);
862
863 return;
864 }
865}
866
867static void __init nubus_scan_bus(void)
868{
869 int slot;
870
871 pr_info("NuBus: Scanning NuBus slots.\n");
872 for (slot = 9; slot < 15; slot++) {
873 nubus_probe_slot(slot);
874 }
875}
876
877static int __init nubus_init(void)
878{
879 int err;
880
881 if (!MACH_IS_MAC)
882 return 0;
883
884 nubus_proc_init();
885 err = nubus_parent_device_register();
886 if (err)
887 return err;
888 nubus_scan_bus();
889 return 0;
890}
891
892subsys_initcall(nubus_init);