Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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