• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 LIST_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 
not_useful(void * p,int map)60 static 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 
nubus_get_rom(unsigned char ** ptr,int len,int map)70 static 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 
nubus_rewind(unsigned char ** ptr,int len,int map)87 static 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 
nubus_advance(unsigned char ** ptr,int len,int map)100 static 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 
nubus_move(unsigned char ** ptr,int len,int map)113 static 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 
nubus_expand32(long foo)133 static inline long nubus_expand32(long foo)
134 {
135 	if (foo & 0x00800000)	/* 24bit negative */
136 		foo |= 0xFF000000;
137 	return foo;
138 }
139 
nubus_rom_addr(int slot)140 static 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 
nubus_dirptr(const struct nubus_dirent * nd)149 unsigned 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 
nubus_get_rsrc_mem(void * dest,const struct nubus_dirent * dirent,unsigned int len)163 void 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 }
174 EXPORT_SYMBOL(nubus_get_rsrc_mem);
175 
nubus_get_rsrc_str(char * dest,const struct nubus_dirent * dirent,unsigned int len)176 unsigned 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 }
194 EXPORT_SYMBOL(nubus_get_rsrc_str);
195 
nubus_seq_write_rsrc_mem(struct seq_file * m,const struct nubus_dirent * dirent,unsigned int len)196 void 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 
nubus_get_root_dir(const struct nubus_board * board,struct nubus_dir * dir)219 int 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 }
227 EXPORT_SYMBOL(nubus_get_root_dir);
228 
229 /* This is a slyly renamed version of the above */
nubus_get_func_dir(const struct nubus_rsrc * fres,struct nubus_dir * dir)230 int 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 }
237 EXPORT_SYMBOL(nubus_get_func_dir);
238 
nubus_get_board_dir(const struct nubus_board * board,struct nubus_dir * dir)239 int 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 }
256 EXPORT_SYMBOL(nubus_get_board_dir);
257 
nubus_get_subdir(const struct nubus_dirent * ent,struct nubus_dir * dir)258 int 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 }
266 EXPORT_SYMBOL(nubus_get_subdir);
267 
nubus_readdir(struct nubus_dir * nd,struct nubus_dirent * ent)268 int 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 }
295 EXPORT_SYMBOL(nubus_readdir);
296 
nubus_rewinddir(struct nubus_dir * dir)297 int nubus_rewinddir(struct nubus_dir *dir)
298 {
299 	dir->ptr = dir->base;
300 	dir->done = 0;
301 	return 0;
302 }
303 EXPORT_SYMBOL(nubus_rewinddir);
304 
305 /* Driver interface functions, more or less like in pci.c */
306 
nubus_first_rsrc_or_null(void)307 struct 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 }
312 EXPORT_SYMBOL(nubus_first_rsrc_or_null);
313 
nubus_next_rsrc_or_null(struct nubus_rsrc * from)314 struct 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 }
320 EXPORT_SYMBOL(nubus_next_rsrc_or_null);
321 
322 int
nubus_find_rsrc(struct nubus_dir * dir,unsigned char rsrc_type,struct nubus_dirent * ent)323 nubus_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 }
332 EXPORT_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 
nubus_get_block_rsrc_dir(struct nubus_board * board,struct proc_dir_entry * procdir,const struct nubus_dirent * parent)338 static 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 
nubus_get_display_vidmode(struct nubus_board * board,struct proc_dir_entry * procdir,const struct nubus_dirent * parent)358 static 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 
nubus_get_display_resource(struct nubus_rsrc * fres,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)390 static 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 
nubus_get_network_resource(struct nubus_rsrc * fres,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)412 static 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 
nubus_get_cpu_resource(struct nubus_rsrc * fres,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)434 static 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 
nubus_get_private_resource(struct nubus_rsrc * fres,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)467 static 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 
489 static struct nubus_rsrc * __init
nubus_get_functional_resource(struct nubus_board * board,int slot,const struct nubus_dirent * parent)490 nubus_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. */
nubus_get_icon(struct nubus_board * board,struct proc_dir_entry * procdir,const struct nubus_dirent * ent)585 static 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 
nubus_get_vendorinfo(struct nubus_board * board,struct proc_dir_entry * procdir,const struct nubus_dirent * parent)604 static 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 
nubus_get_board_resource(struct nubus_board * board,int slot,const struct nubus_dirent * parent)631 static 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 
nubus_add_board(int slot,int bytelanes)717 static 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 
nubus_probe_slot(int slot)829 static 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 
nubus_scan_bus(void)860 static 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 
nubus_init(void)870 static 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 
885 subsys_initcall(nubus_init);
886