xref: /openbmc/linux/drivers/nubus/nubus.c (revision 72b44f65)
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 /* 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 
not_useful(void * p,int map)67 static 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 
nubus_get_rom(unsigned char ** ptr,int len,int map)77 static 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 
nubus_rewind(unsigned char ** ptr,int len,int map)94 static 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 
nubus_advance(unsigned char ** ptr,int len,int map)107 static 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 
nubus_move(unsigned char ** ptr,int len,int map)120 static 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 
nubus_expand32(long foo)140 static inline long nubus_expand32(long foo)
141 {
142 	if (foo & 0x00800000)	/* 24bit negative */
143 		foo |= 0xFF000000;
144 	return foo;
145 }
146 
nubus_rom_addr(int slot)147 static 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 
nubus_dirptr(const struct nubus_dirent * nd)156 unsigned 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 
nubus_get_rsrc_mem(void * dest,const struct nubus_dirent * dirent,unsigned int len)170 void 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 }
181 EXPORT_SYMBOL(nubus_get_rsrc_mem);
182 
nubus_get_rsrc_str(char * dest,const struct nubus_dirent * dirent,unsigned int len)183 unsigned 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 }
201 EXPORT_SYMBOL(nubus_get_rsrc_str);
202 
nubus_seq_write_rsrc_mem(struct seq_file * m,const struct nubus_dirent * dirent,unsigned int len)203 void 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 
nubus_get_root_dir(const struct nubus_board * board,struct nubus_dir * dir)226 int 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 }
234 EXPORT_SYMBOL(nubus_get_root_dir);
235 
236 /* This is a slyly renamed version of the above */
nubus_get_func_dir(const struct nubus_rsrc * fres,struct nubus_dir * dir)237 int 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 }
244 EXPORT_SYMBOL(nubus_get_func_dir);
245 
nubus_get_board_dir(const struct nubus_board * board,struct nubus_dir * dir)246 int 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 }
263 EXPORT_SYMBOL(nubus_get_board_dir);
264 
nubus_get_subdir(const struct nubus_dirent * ent,struct nubus_dir * dir)265 int 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 }
273 EXPORT_SYMBOL(nubus_get_subdir);
274 
nubus_readdir(struct nubus_dir * nd,struct nubus_dirent * ent)275 int 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 }
302 EXPORT_SYMBOL(nubus_readdir);
303 
nubus_rewinddir(struct nubus_dir * dir)304 int nubus_rewinddir(struct nubus_dir *dir)
305 {
306 	dir->ptr = dir->base;
307 	dir->done = 0;
308 	return 0;
309 }
310 EXPORT_SYMBOL(nubus_rewinddir);
311 
312 /* Driver interface functions, more or less like in pci.c */
313 
nubus_first_rsrc_or_null(void)314 struct 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 }
319 EXPORT_SYMBOL(nubus_first_rsrc_or_null);
320 
nubus_next_rsrc_or_null(struct nubus_rsrc * from)321 struct 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 }
327 EXPORT_SYMBOL(nubus_next_rsrc_or_null);
328 
329 int
nubus_find_rsrc(struct nubus_dir * dir,unsigned char rsrc_type,struct nubus_dirent * ent)330 nubus_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 }
339 EXPORT_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 
nubus_get_block_rsrc_dir(struct nubus_board * board,struct proc_dir_entry * procdir,const struct nubus_dirent * parent)345 static 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 
nubus_get_display_vidmode(struct nubus_board * board,struct proc_dir_entry * procdir,const struct nubus_dirent * parent)365 static 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 
nubus_get_display_resource(struct nubus_rsrc * fres,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)397 static 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 
nubus_get_network_resource(struct nubus_rsrc * fres,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)419 static 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 
nubus_get_cpu_resource(struct nubus_rsrc * fres,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)441 static 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 
nubus_get_private_resource(struct nubus_rsrc * fres,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)474 static 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 
496 static struct nubus_rsrc * __init
nubus_get_functional_resource(struct nubus_board * board,int slot,const struct nubus_dirent * parent)497 nubus_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. */
nubus_get_icon(struct nubus_board * board,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)592 static 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 
nubus_get_vendorinfo(struct nubus_board * board,struct proc_dir_entry * procdir,const struct nubus_dirent * parent)611 static 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 
nubus_get_board_resource(struct nubus_board * board,int slot,const struct nubus_dirent * parent)638 static 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 
nubus_add_board(int slot,int bytelanes)724 static 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 
nubus_probe_slot(int slot)836 static 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 
nubus_scan_bus(void)867 static 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 
nubus_init(void)877 static 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 
892 subsys_initcall(nubus_init);
893