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