Linux Audio

Check our new training course

Loading...
v5.9
  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);
v3.5.6
 
   1/*
   2 *	Macintosh Nubus Interface Code
   3 *
   4 *      Originally by Alan Cox
   5 *
   6 *      Mostly rewritten by David Huggins-Daines, C. Scott Ananian,
   7 *      and others.
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/kernel.h>
  12#include <linux/string.h>
  13#include <linux/nubus.h>
  14#include <linux/errno.h>
  15#include <linux/init.h>
  16#include <linux/delay.h>
  17#include <linux/module.h>
 
  18#include <linux/slab.h>
  19#include <asm/setup.h>
  20#include <asm/page.h>
  21#include <asm/hwtest.h>
  22#include <linux/proc_fs.h>
  23#include <asm/mac_via.h>
  24#include <asm/mac_oss.h>
  25
  26extern void via_nubus_init(void);
  27extern void oss_nubus_init(void);
  28
  29/* Constants */
  30
  31/* This is, of course, the size in bytelanes, rather than the size in
  32   actual bytes */
  33#define FORMAT_BLOCK_SIZE 20
  34#define ROM_DIR_OFFSET 0x24
  35
  36#define NUBUS_TEST_PATTERN 0x5A932BC7
  37
  38/* Define this if you like to live dangerously - it is known not to
  39   work on pretty much every machine except the Quadra 630 and the LC
  40   III. */
  41#undef I_WANT_TO_PROBE_SLOT_ZERO
  42
  43/* This sometimes helps combat failure to boot */
  44#undef TRY_TO_DODGE_WSOD
  45
  46/* Globals */
  47
  48struct nubus_dev*   nubus_devices;
  49struct nubus_board* nubus_boards;
  50
  51/* Meaning of "bytelanes":
  52
  53   The card ROM may appear on any or all bytes of each long word in
  54   NuBus memory.  The low 4 bits of the "map" value found in the
  55   format block (at the top of the slot address space, as well as at
  56   the top of the MacOS ROM) tells us which bytelanes, i.e. which byte
  57   offsets within each longword, are valid.  Thus:
  58
  59   A map of 0x0f, as found in the MacOS ROM, means that all bytelanes
  60   are valid.
  61
  62   A map of 0xf0 means that no bytelanes are valid (We pray that we
  63   will never encounter this, but stranger things have happened)
  64
  65   A map of 0xe1 means that only the MSB of each long word is actually
  66   part of the card ROM.  (We hope to never encounter NuBus on a
  67   little-endian machine.  Again, stranger things have happened)
  68
  69   A map of 0x78 means that only the LSB of each long word is valid.
  70
  71   Etcetera, etcetera.  Hopefully this clears up some confusion over
  72   what the following code actually does.  */
  73 
  74static inline int not_useful(void *p, int map)
  75{
  76	unsigned long pv=(unsigned long)p;
 
  77	pv &= 3;
  78	if(map & (1<<pv))
  79		return 0;
  80	return 1;
  81}
  82 
  83static unsigned long nubus_get_rom(unsigned char **ptr, int len, int map)
  84{
  85	/* This will hold the result */
  86	unsigned long v = 0;
  87	unsigned char *p = *ptr;
  88
  89	while(len)
  90	{
  91		v <<= 8;
  92		while(not_useful(p,map))
  93			p++;
  94		v |= *p++;
  95		len--;
  96	}
  97	*ptr = p;
  98	return v;
  99}
 100
 101static void nubus_rewind(unsigned char **ptr, int len, int map)
 102{
 103	unsigned char *p=*ptr;
 104
 105	/* Sanity check */
 106	if(len > 65536)
 107		printk(KERN_ERR "rewind of 0x%08x!\n", len);
 108	while(len)
 109	{
 110		do
 111		{
 112			p--;
 113		}
 114		while(not_useful(p, map));
 115		len--;
 116	}
 117	*ptr=p;
 118}
 119
 120static void nubus_advance(unsigned char **ptr, int len, int map)
 121{
 122	unsigned char *p = *ptr;
 123	if(len>65536)
 124		printk(KERN_ERR "advance of 0x%08x!\n", len);
 125	while(len)
 126	{
 127		while(not_useful(p,map))
 128			p++;
 129		p++;
 130		len--;
 131	}
 132	*ptr = p;
 133}
 134
 135static void nubus_move(unsigned char **ptr, int len, int map)
 136{
 137	if(len > 0)
 
 
 138		nubus_advance(ptr, len, map);
 139	else if(len < 0)
 140		nubus_rewind(ptr, -len, map);
 
 
 
 141}
 142
 143/* Now, functions to read the sResource tree */
 144
 145/* Each sResource entry consists of a 1-byte ID and a 3-byte data
 146   field.  If that data field contains an offset, then obviously we
 147   have to expand it from a 24-bit signed number to a 32-bit signed
 148   number. */
 149
 150static inline long nubus_expand32(long foo)
 151{
 152	if(foo & 0x00800000)	/* 24bit negative */
 153		foo |= 0xFF000000;
 154	return foo;
 155}
 156
 157static inline void *nubus_rom_addr(int slot)
 158{	
 159	/*
 160	 *	Returns the first byte after the card. We then walk
 161	 *	backwards to get the lane register and the config
 162	 */
 163	return (void *)(0xF1000000+(slot<<24));
 164}
 165
 166static unsigned char *nubus_dirptr(const struct nubus_dirent *nd)
 167{
 168	unsigned char *p = nd->base;
 
 169	/* Essentially, just step over the bytelanes using whatever
 170	   offset we might have found */
 171	nubus_move(&p, nubus_expand32(nd->data), nd->mask);
 172	/* And return the value */
 173	return p;
 174}
 175
 176/* These two are for pulling resource data blocks (i.e. stuff that's
 177   pointed to with offsets) out of the card ROM. */
 178
 179void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent* dirent,
 180			int len)
 181{
 182	unsigned char *t = (unsigned char *)dest;
 183	unsigned char *p = nubus_dirptr(dirent);
 184	while(len)
 185	{
 186		*t++ = nubus_get_rom(&p, 1, dirent->mask);
 187		len--;
 188	}
 189}
 190EXPORT_SYMBOL(nubus_get_rsrc_mem);
 191
 192void nubus_get_rsrc_str(void *dest, const struct nubus_dirent* dirent,
 193			int len)
 194{
 195	unsigned char *t=(unsigned char *)dest;
 196	unsigned char *p = nubus_dirptr(dirent);
 197	while(len)
 198	{
 199		*t = nubus_get_rom(&p, 1, dirent->mask);
 200		if(!*t++)
 
 201			break;
 
 202		len--;
 203	}
 
 
 
 204}
 205EXPORT_SYMBOL(nubus_get_rsrc_str);
 206
 207int nubus_get_root_dir(const struct nubus_board* board,
 208		       struct nubus_dir* dir)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 209{
 210	dir->ptr = dir->base = board->directory;
 211	dir->done = 0;
 212	dir->mask = board->lanes;
 213	return 0;
 214}
 215EXPORT_SYMBOL(nubus_get_root_dir);
 216
 217/* This is a slyly renamed version of the above */
 218int nubus_get_func_dir(const struct nubus_dev* dev,
 219		       struct nubus_dir* dir)
 220{
 221	dir->ptr = dir->base = dev->directory;
 222	dir->done = 0;
 223	dir->mask = dev->board->lanes;
 224	return 0;
 225}
 226EXPORT_SYMBOL(nubus_get_func_dir);
 227
 228int nubus_get_board_dir(const struct nubus_board* board,
 229			struct nubus_dir* dir)
 230{
 231	struct nubus_dirent ent;
 232	
 233	dir->ptr = dir->base = board->directory;
 234	dir->done = 0;
 235	dir->mask = board->lanes;
 236
 237	/* Now dereference it (the first directory is always the board
 238	   directory) */
 239	if (nubus_readdir(dir, &ent) == -1)
 240		return -1;
 241	if (nubus_get_subdir(&ent, dir) == -1)
 242		return -1;
 243	return 0;
 244}
 245EXPORT_SYMBOL(nubus_get_board_dir);
 246
 247int nubus_get_subdir(const struct nubus_dirent *ent,
 248		     struct nubus_dir *dir)
 249{
 250	dir->ptr = dir->base = nubus_dirptr(ent);
 251	dir->done = 0;
 252	dir->mask = ent->mask;
 253	return 0;
 254}
 255EXPORT_SYMBOL(nubus_get_subdir);
 256
 257int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
 258{
 259	u32 resid;
 
 260	if (nd->done)
 261		return -1;
 262
 263	/* Do this first, otherwise nubus_rewind & co are off by 4 */
 264	ent->base = nd->ptr;
 265
 266	/* This moves nd->ptr forward */
 267	resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
 268
 269	/* EOL marker, as per the Apple docs */
 270	if((resid&0xff000000) == 0xff000000)
 271	{
 272		/* Mark it as done */
 273		nd->done = 1;
 274		return -1;
 275	}
 276
 277	/* First byte is the resource ID */
 278	ent->type  = resid >> 24;
 279	/* Low 3 bytes might contain data (or might not) */
 280	ent->data = resid & 0xffffff;
 281	ent->mask  = nd->mask;
 282	return 0;
 283}
 284EXPORT_SYMBOL(nubus_readdir);
 285
 286int nubus_rewinddir(struct nubus_dir* dir)
 287{
 288	dir->ptr = dir->base;
 
 289	return 0;
 290}
 291EXPORT_SYMBOL(nubus_rewinddir);
 292
 293/* Driver interface functions, more or less like in pci.c */
 294
 295struct nubus_dev*
 296nubus_find_device(unsigned short category,
 297		  unsigned short type,
 298		  unsigned short dr_hw,
 299		  unsigned short dr_sw,
 300		  const struct nubus_dev* from)
 301{
 302	struct nubus_dev* itor =
 303		from ? from->next : nubus_devices;
 304
 305	while (itor) {
 306		if (itor->category == category
 307		    && itor->type == type
 308		    && itor->dr_hw == dr_hw
 309		    && itor->dr_sw == dr_sw)
 310			return itor;
 311		itor = itor->next;
 312	}
 313	return NULL;
 314}
 315EXPORT_SYMBOL(nubus_find_device);
 316
 317struct nubus_dev*
 318nubus_find_type(unsigned short category,
 319		unsigned short type,
 320		const struct nubus_dev* from)
 321{
 322	struct nubus_dev* itor =
 323		from ? from->next : nubus_devices;
 324
 325	while (itor) {
 326		if (itor->category == category
 327		    && itor->type == type)
 328			return itor;
 329		itor = itor->next;
 330	}
 331	return NULL;
 332}
 333EXPORT_SYMBOL(nubus_find_type);
 334
 335struct nubus_dev*
 336nubus_find_slot(unsigned int slot,
 337		const struct nubus_dev* from)
 338{
 339	struct nubus_dev* itor =
 340		from ? from->next : nubus_devices;
 341	
 342	while (itor) {
 343		if (itor->board->slot == slot)
 344			return itor;
 345		itor = itor->next;
 346	}
 347	return NULL;
 348}
 349EXPORT_SYMBOL(nubus_find_slot);
 350
 351int
 352nubus_find_rsrc(struct nubus_dir* dir, unsigned char rsrc_type,
 353		struct nubus_dirent* ent)
 354{
 355	while (nubus_readdir(dir, ent) != -1) {
 356		if (ent->type == rsrc_type)
 357			return 0;
 358	}	
 359	return -1;
 360}
 361EXPORT_SYMBOL(nubus_find_rsrc);
 362
 363/* Initialization functions - decide which slots contain stuff worth
 364   looking at, and print out lots and lots of information from the
 365   resource blocks. */
 366
 367/* FIXME: A lot of this stuff will eventually be useful after
 368   initialization, for intelligently probing Ethernet and video chips,
 369   among other things.  The rest of it should go in the /proc code.
 370   For now, we just use it to give verbose boot logs. */
 
 
 
 
 
 
 
 
 371
 372static int __init nubus_show_display_resource(struct nubus_dev* dev,
 373					      const struct nubus_dirent* ent)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 374{
 375	switch (ent->type) {
 376	case NUBUS_RESID_GAMMADIR:
 377		printk(KERN_INFO "    gamma directory offset: 0x%06x\n", ent->data);
 
 378		break;
 379	case 0x0080 ... 0x0085:
 380		printk(KERN_INFO "    mode %02X info offset: 0x%06x\n",
 381		       ent->type, ent->data);
 
 382		break;
 383	default:
 384		printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
 385		       ent->type, ent->data);
 
 386	}
 387	return 0;
 388}
 389
 390static int __init nubus_show_network_resource(struct nubus_dev* dev,
 391					      const struct nubus_dirent* ent)
 
 392{
 393	switch (ent->type) {
 394	case NUBUS_RESID_MAC_ADDRESS:
 395	{
 396		char addr[6];
 397		int i;
 398		
 399		nubus_get_rsrc_mem(addr, ent, 6);
 400		printk(KERN_INFO "    MAC address: ");
 401		for (i = 0; i < 6; i++)
 402			printk("%02x%s", addr[i] & 0xff,
 403			       i == 5 ? "" : ":");
 404		printk("\n");
 405		break;
 406	}
 407	default:
 408		printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
 409		       ent->type, ent->data);
 
 410	}
 411	return 0;
 412}
 413
 414static int __init nubus_show_cpu_resource(struct nubus_dev* dev,
 415					  const struct nubus_dirent* ent)
 
 416{
 417	switch (ent->type) {
 418	case NUBUS_RESID_MEMINFO:
 419	{
 420		unsigned long meminfo[2];
 
 421		nubus_get_rsrc_mem(&meminfo, ent, 8);
 422		printk(KERN_INFO "    memory: [ 0x%08lx 0x%08lx ]\n",
 423		       meminfo[0], meminfo[1]);
 
 424		break;
 425	}
 426	case NUBUS_RESID_ROMINFO:
 427	{
 428		unsigned long rominfo[2];
 
 429		nubus_get_rsrc_mem(&rominfo, ent, 8);
 430		printk(KERN_INFO "    ROM:    [ 0x%08lx 0x%08lx ]\n",
 431		       rominfo[0], rominfo[1]);
 
 432		break;
 433	}
 434	default:
 435		printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
 436		       ent->type, ent->data);
 
 437	}
 438	return 0;
 439}
 440
 441static int __init nubus_show_private_resource(struct nubus_dev* dev,
 442					      const struct nubus_dirent* ent)
 
 443{
 444	switch (dev->category) {
 445	case NUBUS_CAT_DISPLAY:
 446		nubus_show_display_resource(dev, ent);
 447		break;
 448	case NUBUS_CAT_NETWORK:
 449		nubus_show_network_resource(dev, ent);
 450		break;
 451	case NUBUS_CAT_CPU:
 452		nubus_show_cpu_resource(dev, ent);
 453		break;
 454	default:
 455		printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
 456		       ent->type, ent->data);
 
 457	}
 458	return 0;
 459}
 460
 461static struct nubus_dev* __init
 462	   nubus_get_functional_resource(struct nubus_board* board,
 463					 int slot,
 464					 const struct nubus_dirent* parent)
 465{
 466	struct nubus_dir    dir;
 467	struct nubus_dirent ent;
 468	struct nubus_dev*   dev;
 469	
 470	printk(KERN_INFO "  Function 0x%02x:\n", parent->type);
 471	nubus_get_subdir(parent, &dir);
 
 472
 473	/* Apple seems to have botched the ROM on the IIx */
 474	if (slot == 0 && (unsigned long)dir.base % 2)
 475		dir.base += 1;
 476	
 477	if (console_loglevel >= 10)
 478		printk(KERN_DEBUG "nubus_get_functional_resource: parent is 0x%p, dir is 0x%p\n",
 479		       parent->base, dir.base);
 480
 481	/* Actually we should probably panic if this fails */
 482	if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL)
 483		return NULL;	
 484	dev->resid = parent->type;
 485	dev->directory = dir.base;
 486	dev->board = board;
 487	
 488	while (nubus_readdir(&dir, &ent) != -1)
 489	{
 490		switch(ent.type)
 491		{
 492		case NUBUS_RESID_TYPE:
 493		{
 494			unsigned short nbtdata[4];
 
 495			nubus_get_rsrc_mem(nbtdata, &ent, 8);
 496			dev->category = nbtdata[0];
 497			dev->type     = nbtdata[1];
 498			dev->dr_sw    = nbtdata[2];
 499			dev->dr_hw    = nbtdata[3];
 500			printk(KERN_INFO "    type: [cat 0x%x type 0x%x hw 0x%x sw 0x%x]\n",
 501			       nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
 
 502			break;
 503		}
 504		case NUBUS_RESID_NAME:
 505		{
 506			nubus_get_rsrc_str(dev->name, &ent, 64);
 507			printk(KERN_INFO "    name: %s\n", dev->name);
 
 
 
 
 508			break;
 509		}
 510		case NUBUS_RESID_DRVRDIR:
 511		{
 512			/* MacOS driver.  If we were NetBSD we might
 513			   use this :-) */
 514			struct nubus_dir drvr_dir;
 515			struct nubus_dirent drvr_ent;
 516			nubus_get_subdir(&ent, &drvr_dir);
 517			nubus_readdir(&drvr_dir, &drvr_ent);
 518			dev->driver = nubus_dirptr(&drvr_ent);
 519			printk(KERN_INFO "    driver at: 0x%p\n",
 520			       dev->driver);
 521			break;
 522		}
 523		case NUBUS_RESID_MINOR_BASEOS:
 
 524			/* We will need this in order to support
 525			   multiple framebuffers.  It might be handy
 526			   for Ethernet as well */
 527			nubus_get_rsrc_mem(&dev->iobase, &ent, 4);
 528			printk(KERN_INFO "    memory offset: 0x%08lx\n",
 529			       dev->iobase);
 
 
 530			break;
 
 531		case NUBUS_RESID_MINOR_LENGTH:
 
 532			/* Ditto */
 533			nubus_get_rsrc_mem(&dev->iosize, &ent, 4);
 534			printk(KERN_INFO "    memory length: 0x%08lx\n",
 535			       dev->iosize);
 536			break;			
 
 
 
 537		case NUBUS_RESID_FLAGS:
 538			dev->flags = ent.data;
 539			printk(KERN_INFO "    flags: 0x%06x\n", dev->flags);
 540			break;
 541		case NUBUS_RESID_HWDEVID:
 542			dev->hwdevid = ent.data;
 543			printk(KERN_INFO "    hwdevid: 0x%06x\n", dev->hwdevid);
 544			break;
 545		default:
 546			/* Local/Private resources have their own
 547			   function */
 548			nubus_show_private_resource(dev, &ent);
 549		}
 550	}
 551		
 552	return dev;
 553}
 554
 555/* This is cool. */
 556static int __init nubus_get_vidnames(struct nubus_board* board,
 557				     const struct nubus_dirent* parent)
 558{
 559	struct nubus_dir    dir;
 560	struct nubus_dirent ent;
 561	/* FIXME: obviously we want to put this in a header file soon */
 562	struct vidmode {
 563		u32 size;
 564		/* Don't know what this is yet */
 565		u16 id;
 566		/* Longest one I've seen so far is 26 characters */
 567		char name[32];
 568	};
 569
 570	printk(KERN_INFO "    video modes supported:\n");
 571	nubus_get_subdir(parent, &dir);
 572	if (console_loglevel >= 10)
 573		printk(KERN_DEBUG "nubus_get_vidnames: parent is 0x%p, dir is 0x%p\n",
 574		       parent->base, dir.base);
 575
 576	while(nubus_readdir(&dir, &ent) != -1)
 577	{
 578		struct vidmode mode;
 579		u32 size;
 580
 581		/* First get the length */
 582		nubus_get_rsrc_mem(&size, &ent, 4);
 583		
 584		/* Now clobber the whole thing */
 585		if (size > sizeof(mode) - 1)
 586			size = sizeof(mode) - 1;
 587		memset(&mode, 0, sizeof(mode));
 588		nubus_get_rsrc_mem(&mode, &ent, size);
 589		printk (KERN_INFO "      %02X: (%02X) %s\n", ent.type,
 590			mode.id, mode.name);
 591	}
 592	return 0;
 593}
 594
 595/* This is *really* cool. */
 596static int __init nubus_get_icon(struct nubus_board* board,
 597				 const struct nubus_dirent* ent)
 
 598{
 599	/* Should be 32x32 if my memory serves me correctly */
 600	unsigned char icon[128];
 601	int x, y;
 602	
 603	nubus_get_rsrc_mem(&icon, ent, 128);
 604	printk(KERN_INFO "    icon:\n");
 
 
 
 
 
 605
 606	/* We should actually plot these somewhere in the framebuffer
 607	   init.  This is just to demonstrate that they do, in fact,
 608	   exist */
 609	for (y = 0; y < 32; y++) {
 610		printk(KERN_INFO "      ");
 611		for (x = 0; x < 32; x++) {
 612			if (icon[y*4 + x/8]
 613			    & (0x80 >> (x%8)))
 614				printk("*");
 615			else
 616				printk(" ");
 617		}
 618		printk("\n");
 619	}
 620	return 0;
 621}
 622
 623static int __init nubus_get_vendorinfo(struct nubus_board* board,
 624				       const struct nubus_dirent* parent)
 
 625{
 626	struct nubus_dir    dir;
 627	struct nubus_dirent ent;
 628	static char* vendor_fields[6] = {"ID", "serial", "revision",
 629					 "part", "date", "unknown field"};
 630
 631	printk(KERN_INFO "    vendor info:\n");
 632	nubus_get_subdir(parent, &dir);
 633	if (console_loglevel >= 10)
 634		printk(KERN_DEBUG "nubus_get_vendorinfo: parent is 0x%p, dir is 0x%p\n",
 635		       parent->base, dir.base);
 636
 637	while(nubus_readdir(&dir, &ent) != -1)
 638	{
 639		char name[64];
 640		
 
 641		/* These are all strings, we think */
 642		nubus_get_rsrc_str(name, &ent, 64);
 643		if (ent.type > 5)
 644			ent.type = 5;
 645		printk(KERN_INFO "    %s: %s\n",
 646		       vendor_fields[ent.type-1], name);
 647	}
 648	return 0;
 649}
 650
 651static int __init nubus_get_board_resource(struct nubus_board* board, int slot,
 652					   const struct nubus_dirent* parent)
 653{
 654	struct nubus_dir    dir;
 655	struct nubus_dirent ent;
 656	
 
 657	nubus_get_subdir(parent, &dir);
 658	if (console_loglevel >= 10)
 659		printk(KERN_DEBUG "nubus_get_board_resource: parent is 0x%p, dir is 0x%p\n",
 660		       parent->base, dir.base);
 661
 662	while(nubus_readdir(&dir, &ent) != -1)
 663	{
 664		switch (ent.type) {
 665		case NUBUS_RESID_TYPE:
 666		{
 667			unsigned short nbtdata[4];
 668			/* This type is always the same, and is not
 669			   useful except insofar as it tells us that
 670			   we really are looking at a board resource. */
 671			nubus_get_rsrc_mem(nbtdata, &ent, 8);
 672			printk(KERN_INFO "    type: [cat 0x%x type 0x%x hw 0x%x sw 0x%x]\n",
 673			       nbtdata[0], nbtdata[1], nbtdata[2],
 674			       nbtdata[3]);
 675			if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
 676			    nbtdata[2] != 0 || nbtdata[3] != 0)
 677				printk(KERN_ERR "this sResource is not a board resource!\n");
 
 
 678			break;
 679		}
 680		case NUBUS_RESID_NAME:
 681			nubus_get_rsrc_str(board->name, &ent, 64);
 682			printk(KERN_INFO "    name: %s\n", board->name);
 
 
 
 
 
 683			break;
 
 684		case NUBUS_RESID_ICON:
 685			nubus_get_icon(board, &ent);
 686			break;
 687		case NUBUS_RESID_BOARDID:
 688			printk(KERN_INFO "    board id: 0x%x\n", ent.data);
 
 689			break;
 690		case NUBUS_RESID_PRIMARYINIT:
 691			printk(KERN_INFO "    primary init offset: 0x%06x\n", ent.data);
 
 692			break;
 693		case NUBUS_RESID_VENDORINFO:
 694			nubus_get_vendorinfo(board, &ent);
 695			break;
 696		case NUBUS_RESID_FLAGS:
 697			printk(KERN_INFO "    flags: 0x%06x\n", ent.data);
 
 698			break;
 699		case NUBUS_RESID_HWDEVID:
 700			printk(KERN_INFO "    hwdevid: 0x%06x\n", ent.data);
 
 701			break;
 702		case NUBUS_RESID_SECONDINIT:
 703			printk(KERN_INFO "    secondary init offset: 0x%06x\n", ent.data);
 
 
 704			break;
 705			/* WTF isn't this in the functional resources? */ 
 706		case NUBUS_RESID_VIDNAMES:
 707			nubus_get_vidnames(board, &ent);
 
 
 708			break;
 709			/* Same goes for this */
 710		case NUBUS_RESID_VIDMODES:
 711			printk(KERN_INFO "    video mode parameter directory offset: 0x%06x\n",
 712			       ent.data);
 713			break;			
 
 714		default:
 715			printk(KERN_INFO "    unknown resource %02X, data 0x%06x\n",
 716			       ent.type, ent.data);
 
 717		}
 718	}
 719	return 0;
 720}
 721
 722/* Attempt to bypass the somewhat non-obvious arrangement of
 723   sResources in the motherboard ROM */
 724static void __init nubus_find_rom_dir(struct nubus_board* board)
 725{
 726	unsigned char* rp;
 727	unsigned char* romdir;
 728	struct nubus_dir dir;
 729	struct nubus_dirent ent;
 730
 731	/* Check for the extra directory just under the format block */
 732	rp = board->fblock;
 733	nubus_rewind(&rp, 4, board->lanes);
 734	if (nubus_get_rom(&rp, 4, board->lanes) != NUBUS_TEST_PATTERN) {
 735		/* OK, the ROM was telling the truth */
 736		board->directory = board->fblock;
 737		nubus_move(&board->directory,
 738			   nubus_expand32(board->doffset),
 739			   board->lanes);
 740		return;
 741	}
 742
 743	/* On "slot zero", you have to walk down a few more
 744	   directories to get to the equivalent of a real card's root
 745	   directory.  We don't know what they were smoking when they
 746	   came up with this. */
 747	romdir = nubus_rom_addr(board->slot);
 748	nubus_rewind(&romdir, ROM_DIR_OFFSET, board->lanes);
 749	dir.base = dir.ptr = romdir;
 750	dir.done = 0;
 751	dir.mask = board->lanes;
 752
 753	/* This one points to an "Unknown Macintosh" directory */
 754	if (nubus_readdir(&dir, &ent) == -1)
 755		goto badrom;
 756
 757	if (console_loglevel >= 10)
 758		printk(KERN_INFO "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
 759	/* This one takes us to where we want to go. */
 760	if (nubus_readdir(&dir, &ent) == -1) 
 761		goto badrom;
 762	if (console_loglevel >= 10)
 763		printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
 764	nubus_get_subdir(&ent, &dir);
 765
 766	/* Resource ID 01, also an "Unknown Macintosh" */
 767	if (nubus_readdir(&dir, &ent) == -1) 
 768		goto badrom;
 769	if (console_loglevel >= 10)
 770		printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
 771
 772	/* FIXME: the first one is *not* always the right one.  We
 773	   suspect this has something to do with the ROM revision.
 774	   "The HORROR ROM" (LC-series) uses 0x7e, while "The HORROR
 775	   Continues" (Q630) uses 0x7b.  The DAFB Macs evidently use
 776	   something else.  Please run "Slots" on your Mac (see
 777	   include/linux/nubus.h for where to get this program) and
 778	   tell us where the 'SiDirPtr' for Slot 0 is.  If you feel
 779	   brave, you should also use MacsBug to walk down the ROM
 780	   directories like this function does and try to find the
 781	   path to that address... */
 782	if (nubus_readdir(&dir, &ent) == -1)
 783		goto badrom;
 784	if (console_loglevel >= 10)
 785		printk(KERN_DEBUG "nubus_get_rom_dir: entry %02x %06x\n", ent.type, ent.data);
 786	
 787	/* Bwahahahaha... */
 788	nubus_get_subdir(&ent, &dir);
 789	board->directory = dir.base;
 790	return;
 791	
 792	/* Even more evil laughter... */
 793 badrom:
 794	board->directory = board->fblock;
 795	nubus_move(&board->directory, nubus_expand32(board->doffset), board->lanes);
 796	printk(KERN_ERR "nubus_get_rom_dir: ROM weirdness!  Notify the developers...\n");
 797}
 798
 799/* Add a board (might be many devices) to the list */
 800static struct nubus_board* __init nubus_add_board(int slot, int bytelanes)
 801{
 802	struct nubus_board* board;
 803	struct nubus_board** boardp;
 804
 805	unsigned char *rp;
 806	unsigned long dpat;
 807	struct nubus_dir dir;
 808	struct nubus_dirent ent;
 
 809
 810	/* Move to the start of the format block */
 811	rp = nubus_rom_addr(slot);		
 812	nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
 813
 814	/* Actually we should probably panic if this fails */
 815	if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
 816		return NULL;	
 817	board->fblock = rp;
 818
 819	/* Dump the format block for debugging purposes */
 820	if (console_loglevel >= 10) {
 821		int i;
 822		printk(KERN_DEBUG "Slot %X, format block at 0x%p\n",
 823		       slot, rp);
 824		printk(KERN_DEBUG "Format block: ");
 825		for (i = 0; i < FORMAT_BLOCK_SIZE; i += 4) {
 826			unsigned short foo, bar;
 827			foo = nubus_get_rom(&rp, 2, bytelanes);
 828			bar = nubus_get_rom(&rp, 2, bytelanes);
 829			printk("%04x %04x  ", foo, bar);
 830		}
 831		printk("\n");
 832		rp = board->fblock;
 833	}
 834	
 835	board->slot = slot;
 836	board->slot_addr = (unsigned long) nubus_slot_addr(slot);
 837	board->doffset = nubus_get_rom(&rp, 4, bytelanes);
 838	/* rom_length is *supposed* to be the total length of the
 839	 * ROM.  In practice it is the "amount of ROM used to compute
 840	 * the CRC."  So some jokers decide to set it to zero and
 841	 * set the crc to zero so they don't have to do any math.
 842	 * See the Performa 460 ROM, for example.  Those Apple "engineers".
 843	 */
 844	board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
 845	board->crc = nubus_get_rom(&rp, 4, bytelanes);
 846	board->rev = nubus_get_rom(&rp, 1, bytelanes);
 847	board->format = nubus_get_rom(&rp,1, bytelanes);
 848	board->lanes = bytelanes;
 849
 850	/* Directory offset should be small and negative... */
 851	if(!(board->doffset & 0x00FF0000))
 852		printk(KERN_WARNING "Dodgy doffset!\n");
 853	dpat = nubus_get_rom(&rp, 4, bytelanes);
 854	if(dpat != NUBUS_TEST_PATTERN)
 855		printk(KERN_WARNING "Wrong test pattern %08lx!\n", dpat);
 856		
 857	/*
 858	 *	I wonder how the CRC is meant to work -
 859	 *		any takers ?
 860	 * CSA: According to MAC docs, not all cards pass the CRC anyway,
 861	 * since the initial Macintosh ROM releases skipped the check.
 862	 */
 863
 864	/* Attempt to work around slot zero weirdness */
 865	nubus_find_rom_dir(board);
 866	nubus_get_root_dir(board, &dir);	
 
 
 
 867
 868	/* We're ready to rock */
 869	printk(KERN_INFO "Slot %X:\n", slot);
 870
 871	/* Each slot should have one board resource and any number of
 872	   functional resources.  So we'll fill in some fields in the
 873	   struct nubus_board from the board resource, then walk down
 874	   the list of functional resources, spinning out a nubus_dev
 875	   for each of them. */
 
 876	if (nubus_readdir(&dir, &ent) == -1) {
 877		/* We can't have this! */
 878		printk(KERN_ERR "Board resource not found!\n");
 879		return NULL;
 880	} else {
 881		printk(KERN_INFO "  Board resource:\n");
 882		nubus_get_board_resource(board, slot, &ent);
 883	}
 884
 885	/* Aaaarrrrgghh!  The LC III motherboard has *two* board
 886	   resources.  I have no idea WTF to do about this. */
 
 
 
 
 887
 888	while (nubus_readdir(&dir, &ent) != -1) {
 889		struct nubus_dev*  dev;
 890		struct nubus_dev** devp;
 891		dev = nubus_get_functional_resource(board, slot, &ent);
 892		if (dev == NULL)
 893			continue;
 894
 895		/* We zeroed this out above */
 896		if (board->first_dev == NULL)
 897			board->first_dev = dev;
 898		
 899		/* Put it on the global NuBus device chain. Keep entries in order. */
 900		for (devp=&nubus_devices; *devp!=NULL; devp=&((*devp)->next))
 901			/* spin */;
 902		*devp = dev;
 903		dev->next = NULL;		
 904	}
 905
 906	/* Put it on the global NuBus board chain. Keep entries in order. */
 907	for (boardp=&nubus_boards; *boardp!=NULL; boardp=&((*boardp)->next))
 908		/* spin */;
 909	*boardp = board;
 910	board->next = NULL;
 911	
 912	return board;
 913}
 914
 915void __init nubus_probe_slot(int slot)
 916{
 917	unsigned char dp;
 918	unsigned char* rp;
 919	int i;
 920
 921	rp = nubus_rom_addr(slot);	
 922	for(i = 4; i; i--)
 923	{
 924		unsigned long flags;
 925		int card_present;
 926
 927		rp--;
 928		local_irq_save(flags);
 929		card_present = hwreg_present(rp);
 930		local_irq_restore(flags);
 931	       
 932		if (!card_present)
 933			continue;
 934
 935		printk(KERN_DEBUG "Now probing slot %X at %p\n", slot, rp);
 936		dp = *rp;
 937		if(dp == 0)
 938			continue;
 939
 940		/* The last byte of the format block consists of two
 941		   nybbles which are "mirror images" of each other.
 942		   These show us the valid bytelanes */
 943		if ((((dp>>4) ^ dp) & 0x0F) != 0x0F)
 944			continue;
 945		/* Check that this value is actually *on* one of the
 946		   bytelanes it claims are valid! */
 947		if ((dp & 0x0F) >= (1<<i))
 948			continue;
 949
 950		/* Looks promising.  Let's put it on the list. */
 951		nubus_add_board(slot, dp);
 952
 953		return;
 954	}
 955}
 956
 957#if defined(CONFIG_PROC_FS)
 958
 959/* /proc/nubus stuff */
 960
 961static int sprint_nubus_board(struct nubus_board* board, char* ptr, int len)
 962{
 963	if(len < 100)
 964		return -1;
 965	
 966	sprintf(ptr, "Slot %X: %s\n",
 967		board->slot, board->name);
 968	
 969	return strlen(ptr);
 970}
 971
 972static int nubus_read_proc(char *page, char **start, off_t off,
 973				int count, int *eof, void *data)
 974{
 975	int nprinted, len, begin = 0;
 976	int size = PAGE_SIZE;
 977	struct nubus_board* board;
 978	
 979	len   = sprintf(page, "Nubus devices found:\n");
 980	/* Walk the list of NuBus boards */
 981	for (board = nubus_boards; board != NULL; board = board->next)
 982	{
 983		nprinted = sprint_nubus_board(board, page + len, size - len);
 984		if (nprinted < 0)
 985			break;
 986		len += nprinted;
 987		if (len+begin < off) {
 988			begin += len;
 989			len = 0;
 990		}
 991		if (len+begin >= off+count)
 992			break;
 993	}
 994	if (len+begin < off)
 995		*eof = 1;
 996	off -= begin;
 997	*start = page + off;
 998	len -= off;
 999	if (len>count)
1000		len = count;
1001	if (len<0)
1002		len = 0;
1003	return len;
1004}
1005#endif
1006
1007void __init nubus_scan_bus(void)
1008{
1009	int slot;
1010	/* This might not work on your machine */
1011#ifdef I_WANT_TO_PROBE_SLOT_ZERO
1012	nubus_probe_slot(0);
1013#endif
1014	for(slot = 9; slot < 15; slot++)
1015	{
1016		nubus_probe_slot(slot);
1017	}
1018}
1019
1020static int __init nubus_init(void)
1021{
1022	if (!MACH_IS_MAC) 
 
 
1023		return 0;
1024
1025	/* Initialize the NuBus interrupts */
1026	if (oss_present) {
1027		oss_nubus_init();
1028	} else {
1029		via_nubus_init();
1030	}
1031
1032#ifdef TRY_TO_DODGE_WSOD
1033	/* Rogue Ethernet interrupts can kill the machine if we don't
1034	   do this.  Obviously this is bogus.  Hopefully the local VIA
1035	   gurus can fix the real cause of the problem. */
1036	mdelay(1000);
1037#endif
1038	
1039	/* And probe */
1040	printk("NuBus: Scanning NuBus slots.\n");
1041	nubus_devices = NULL;
1042	nubus_boards  = NULL;
1043	nubus_scan_bus();
1044
1045#ifdef CONFIG_PROC_FS
1046	create_proc_read_entry("nubus", 0, NULL, nubus_read_proc, NULL);
1047	nubus_proc_init();
1048#endif
1049	return 0;
1050}
1051
1052subsys_initcall(nubus_init);