cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nubus.c (22837B)


      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);