diff options
Diffstat (limited to 'drivers/nubus/nubus.c')
| -rw-r--r-- | drivers/nubus/nubus.c | 542 | 
1 files changed, 290 insertions, 252 deletions
| diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index b793727cd4f7..4621ff98138c 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -15,6 +15,7 @@  #include <linux/errno.h>  #include <linux/init.h>  #include <linux/module.h> +#include <linux/seq_file.h>  #include <linux/slab.h>  #include <asm/setup.h>  #include <asm/page.h> @@ -31,8 +32,7 @@  /* Globals */ -struct nubus_dev *nubus_devices; -struct nubus_board *nubus_boards; +LIST_HEAD(nubus_func_rsrcs);  /* Meaning of "bytelanes": @@ -146,7 +146,7 @@ static inline void *nubus_rom_addr(int slot)  	return (void *)(0xF1000000 + (slot << 24));  } -static unsigned char *nubus_dirptr(const struct nubus_dirent *nd) +unsigned char *nubus_dirptr(const struct nubus_dirent *nd)  {  	unsigned char *p = nd->base; @@ -161,7 +161,7 @@ static unsigned char *nubus_dirptr(const struct nubus_dirent *nd)     pointed to with offsets) out of the card ROM. */  void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, -			int len) +			unsigned int len)  {  	unsigned char *t = (unsigned char *)dest;  	unsigned char *p = nubus_dirptr(dirent); @@ -173,21 +173,49 @@ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,  }  EXPORT_SYMBOL(nubus_get_rsrc_mem); -void nubus_get_rsrc_str(void *dest, const struct nubus_dirent *dirent, -			int len) +unsigned int nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, +				unsigned int len)  { -	unsigned char *t = (unsigned char *)dest; +	char *t = dest;  	unsigned char *p = nubus_dirptr(dirent); -	while (len) { -		*t = nubus_get_rom(&p, 1, dirent->mask); -		if (!*t++) +	while (len > 1) { +		unsigned char c = nubus_get_rom(&p, 1, dirent->mask); + +		if (!c)  			break; +		*t++ = c;  		len--;  	} +	if (len > 0) +		*t = '\0'; +	return t - dest;  }  EXPORT_SYMBOL(nubus_get_rsrc_str); +void nubus_seq_write_rsrc_mem(struct seq_file *m, +			      const struct nubus_dirent *dirent, +			      unsigned int len) +{ +	unsigned long buf[32]; +	unsigned int buf_size = sizeof(buf); +	unsigned char *p = nubus_dirptr(dirent); + +	/* If possible, write out full buffers */ +	while (len >= buf_size) { +		unsigned int i; + +		for (i = 0; i < ARRAY_SIZE(buf); i++) +			buf[i] = nubus_get_rom(&p, sizeof(buf[0]), +					       dirent->mask); +		seq_write(m, buf, buf_size); +		len -= buf_size; +	} +	/* If not, write out individual bytes */ +	while (len--) +		seq_putc(m, nubus_get_rom(&p, 1, dirent->mask)); +} +  int nubus_get_root_dir(const struct nubus_board *board,  		       struct nubus_dir *dir)  { @@ -199,12 +227,11 @@ int nubus_get_root_dir(const struct nubus_board *board,  EXPORT_SYMBOL(nubus_get_root_dir);  /* This is a slyly renamed version of the above */ -int nubus_get_func_dir(const struct nubus_dev *dev, -		       struct nubus_dir *dir) +int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir)  { -	dir->ptr = dir->base = dev->directory; +	dir->ptr = dir->base = fres->directory;  	dir->done = 0; -	dir->mask = dev->board->lanes; +	dir->mask = fres->board->lanes;  	return 0;  }  EXPORT_SYMBOL(nubus_get_func_dir); @@ -277,51 +304,20 @@ EXPORT_SYMBOL(nubus_rewinddir);  /* Driver interface functions, more or less like in pci.c */ -struct nubus_dev* -nubus_find_device(unsigned short category, unsigned short type, -		  unsigned short dr_hw, unsigned short dr_sw, -		  const struct nubus_dev *from) -{ -	struct nubus_dev *itor = from ? from->next : nubus_devices; - -	while (itor) { -		if (itor->category == category && itor->type == type && -		    itor->dr_hw == dr_hw && itor->dr_sw == dr_sw) -			return itor; -		itor = itor->next; -	} -	return NULL; -} -EXPORT_SYMBOL(nubus_find_device); - -struct nubus_dev* -nubus_find_type(unsigned short category, unsigned short type, -		const struct nubus_dev *from) +struct nubus_rsrc *nubus_first_rsrc_or_null(void)  { -	struct nubus_dev *itor = from ? from->next : nubus_devices; - -	while (itor) { -		if (itor->category == category && itor->type == type) -			return itor; -		itor = itor->next; -	} -	return NULL; +	return list_first_entry_or_null(&nubus_func_rsrcs, struct nubus_rsrc, +					list);  } -EXPORT_SYMBOL(nubus_find_type); +EXPORT_SYMBOL(nubus_first_rsrc_or_null); -struct nubus_dev* -nubus_find_slot(unsigned int slot, const struct nubus_dev *from) +struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from)  { -	struct nubus_dev *itor = from ? from->next : nubus_devices; - -	while (itor) { -		if (itor->board->slot == slot) -			return itor; -		itor = itor->next; -	} -	return NULL; +	if (list_is_last(&from->list, &nubus_func_rsrcs)) +		return NULL; +	return list_next_entry(from, list);  } -EXPORT_SYMBOL(nubus_find_slot); +EXPORT_SYMBOL(nubus_next_rsrc_or_null);  int  nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type, @@ -339,31 +335,83 @@ EXPORT_SYMBOL(nubus_find_rsrc);     looking at, and print out lots and lots of information from the     resource blocks. */ -/* FIXME: A lot of this stuff will eventually be useful after -   initialization, for intelligently probing Ethernet and video chips, -   among other things.  The rest of it should go in the /proc code. -   For now, we just use it to give verbose boot logs. */ +static int __init nubus_get_block_rsrc_dir(struct nubus_board *board, +					   struct proc_dir_entry *procdir, +					   const struct nubus_dirent *parent) +{ +	struct nubus_dir dir; +	struct nubus_dirent ent; + +	nubus_get_subdir(parent, &dir); +	dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board); -static int __init nubus_show_display_resource(struct nubus_dev *dev, -					      const struct nubus_dirent *ent) +	while (nubus_readdir(&dir, &ent) != -1) { +		u32 size; + +		nubus_get_rsrc_mem(&size, &ent, 4); +		pr_debug("        block (0x%x), size %d\n", ent.type, size); +		nubus_proc_add_rsrc_mem(dir.procdir, &ent, size); +	} +	return 0; +} + +static int __init nubus_get_display_vidmode(struct nubus_board *board, +					    struct proc_dir_entry *procdir, +					    const struct nubus_dirent *parent) +{ +	struct nubus_dir dir; +	struct nubus_dirent ent; + +	nubus_get_subdir(parent, &dir); +	dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board); + +	while (nubus_readdir(&dir, &ent) != -1) { +		switch (ent.type) { +		case 1: /* mVidParams */ +		case 2: /* mTable */ +		{ +			u32 size; + +			nubus_get_rsrc_mem(&size, &ent, 4); +			pr_debug("        block (0x%x), size %d\n", ent.type, +				size); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, size); +			break; +		} +		default: +			pr_debug("        unknown resource 0x%02x, data 0x%06x\n", +				ent.type, ent.data); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0); +		} +	} +	return 0; +} + +static int __init nubus_get_display_resource(struct nubus_rsrc *fres, +					     struct proc_dir_entry *procdir, +					     const struct nubus_dirent *ent)  {  	switch (ent->type) {  	case NUBUS_RESID_GAMMADIR: -		pr_info("    gamma directory offset: 0x%06x\n", ent->data); +		pr_debug("    gamma directory offset: 0x%06x\n", ent->data); +		nubus_get_block_rsrc_dir(fres->board, procdir, ent);  		break;  	case 0x0080 ... 0x0085: -		pr_info("    mode %02X info offset: 0x%06x\n", -		       ent->type, ent->data); +		pr_debug("    mode 0x%02x info offset: 0x%06x\n", +			ent->type, ent->data); +		nubus_get_display_vidmode(fres->board, procdir, ent);  		break;  	default: -		pr_info("    unknown resource %02X, data 0x%06x\n", -		       ent->type, ent->data); +		pr_debug("    unknown resource 0x%02x, data 0x%06x\n", +			ent->type, ent->data); +		nubus_proc_add_rsrc_mem(procdir, ent, 0);  	}  	return 0;  } -static int __init nubus_show_network_resource(struct nubus_dev *dev, -					      const struct nubus_dirent *ent) +static int __init nubus_get_network_resource(struct nubus_rsrc *fres, +					     struct proc_dir_entry *procdir, +					     const struct nubus_dirent *ent)  {  	switch (ent->type) {  	case NUBUS_RESID_MAC_ADDRESS: @@ -371,18 +419,21 @@ static int __init nubus_show_network_resource(struct nubus_dev *dev,  		char addr[6];  		nubus_get_rsrc_mem(addr, ent, 6); -		pr_info("    MAC address: %pM\n", addr); +		pr_debug("    MAC address: %pM\n", addr); +		nubus_proc_add_rsrc_mem(procdir, ent, 6);  		break;  	}  	default: -		pr_info("    unknown resource %02X, data 0x%06x\n", -		       ent->type, ent->data); +		pr_debug("    unknown resource 0x%02x, data 0x%06x\n", +			ent->type, ent->data); +		nubus_proc_add_rsrc_mem(procdir, ent, 0);  	}  	return 0;  } -static int __init nubus_show_cpu_resource(struct nubus_dev *dev, -					  const struct nubus_dirent *ent) +static int __init nubus_get_cpu_resource(struct nubus_rsrc *fres, +					 struct proc_dir_entry *procdir, +					 const struct nubus_dirent *ent)  {  	switch (ent->type) {  	case NUBUS_RESID_MEMINFO: @@ -390,8 +441,9 @@ static int __init nubus_show_cpu_resource(struct nubus_dev *dev,  		unsigned long meminfo[2];  		nubus_get_rsrc_mem(&meminfo, ent, 8); -		pr_info("    memory: [ 0x%08lx 0x%08lx ]\n", -		       meminfo[0], meminfo[1]); +		pr_debug("    memory: [ 0x%08lx 0x%08lx ]\n", +			meminfo[0], meminfo[1]); +		nubus_proc_add_rsrc_mem(procdir, ent, 8);  		break;  	}  	case NUBUS_RESID_ROMINFO: @@ -399,57 +451,60 @@ static int __init nubus_show_cpu_resource(struct nubus_dev *dev,  		unsigned long rominfo[2];  		nubus_get_rsrc_mem(&rominfo, ent, 8); -		pr_info("    ROM:    [ 0x%08lx 0x%08lx ]\n", -		       rominfo[0], rominfo[1]); +		pr_debug("    ROM:    [ 0x%08lx 0x%08lx ]\n", +			rominfo[0], rominfo[1]); +		nubus_proc_add_rsrc_mem(procdir, ent, 8);  		break;  	}  	default: -		pr_info("    unknown resource %02X, data 0x%06x\n", -		       ent->type, ent->data); +		pr_debug("    unknown resource 0x%02x, data 0x%06x\n", +			ent->type, ent->data); +		nubus_proc_add_rsrc_mem(procdir, ent, 0);  	}  	return 0;  } -static int __init nubus_show_private_resource(struct nubus_dev *dev, -					      const struct nubus_dirent *ent) +static int __init nubus_get_private_resource(struct nubus_rsrc *fres, +					     struct proc_dir_entry *procdir, +					     const struct nubus_dirent *ent)  { -	switch (dev->category) { +	switch (fres->category) {  	case NUBUS_CAT_DISPLAY: -		nubus_show_display_resource(dev, ent); +		nubus_get_display_resource(fres, procdir, ent);  		break;  	case NUBUS_CAT_NETWORK: -		nubus_show_network_resource(dev, ent); +		nubus_get_network_resource(fres, procdir, ent);  		break;  	case NUBUS_CAT_CPU: -		nubus_show_cpu_resource(dev, ent); +		nubus_get_cpu_resource(fres, procdir, ent);  		break;  	default: -		pr_info("    unknown resource %02X, data 0x%06x\n", -		       ent->type, ent->data); +		pr_debug("    unknown resource 0x%02x, data 0x%06x\n", +			ent->type, ent->data); +		nubus_proc_add_rsrc_mem(procdir, ent, 0);  	}  	return 0;  } -static struct nubus_dev * __init +static struct nubus_rsrc * __init  nubus_get_functional_resource(struct nubus_board *board, int slot,  			      const struct nubus_dirent *parent)  {  	struct nubus_dir dir;  	struct nubus_dirent ent; -	struct nubus_dev *dev; +	struct nubus_rsrc *fres; -	pr_info("  Function 0x%02x:\n", parent->type); +	pr_debug("  Functional resource 0x%02x:\n", parent->type);  	nubus_get_subdir(parent, &dir); - -	pr_debug("%s: parent is 0x%p, dir is 0x%p\n", -	         __func__, parent->base, dir.base); +	dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);  	/* Actually we should probably panic if this fails */ -	if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL) +	fres = kzalloc(sizeof(*fres), GFP_ATOMIC); +	if (!fres)  		return NULL; -	dev->resid = parent->type; -	dev->directory = dir.base; -	dev->board = board; +	fres->resid = parent->type; +	fres->directory = dir.base; +	fres->board = board;  	while (nubus_readdir(&dir, &ent) != -1) {  		switch (ent.type) { @@ -458,130 +513,96 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,  			unsigned short nbtdata[4];  			nubus_get_rsrc_mem(nbtdata, &ent, 8); -			dev->category = nbtdata[0]; -			dev->type     = nbtdata[1]; -			dev->dr_sw    = nbtdata[2]; -			dev->dr_hw    = nbtdata[3]; -			pr_info("    type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", -			        nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); +			fres->category = nbtdata[0]; +			fres->type     = nbtdata[1]; +			fres->dr_sw    = nbtdata[2]; +			fres->dr_hw    = nbtdata[3]; +			pr_debug("    type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", +				nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);  			break;  		}  		case NUBUS_RESID_NAME:  		{ -			nubus_get_rsrc_str(dev->name, &ent, 64); -			pr_info("    name: %s\n", dev->name); +			char name[64]; +			unsigned int len; + +			len = nubus_get_rsrc_str(name, &ent, sizeof(name)); +			pr_debug("    name: %s\n", name); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);  			break;  		}  		case NUBUS_RESID_DRVRDIR:  		{  			/* MacOS driver.  If we were NetBSD we might  			   use this :-) */ -			struct nubus_dir drvr_dir; -			struct nubus_dirent drvr_ent; - -			nubus_get_subdir(&ent, &drvr_dir); -			nubus_readdir(&drvr_dir, &drvr_ent); -			dev->driver = nubus_dirptr(&drvr_ent); -			pr_info("    driver at: 0x%p\n", dev->driver); +			pr_debug("    driver directory offset: 0x%06x\n", +				ent.data); +			nubus_get_block_rsrc_dir(board, dir.procdir, &ent);  			break;  		}  		case NUBUS_RESID_MINOR_BASEOS: +		{  			/* We will need this in order to support  			   multiple framebuffers.  It might be handy  			   for Ethernet as well */ -			nubus_get_rsrc_mem(&dev->iobase, &ent, 4); -			pr_info("    memory offset: 0x%08lx\n", dev->iobase); +			u32 base_offset; + +			nubus_get_rsrc_mem(&base_offset, &ent, 4); +			pr_debug("    memory offset: 0x%08x\n", base_offset); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);  			break; +		}  		case NUBUS_RESID_MINOR_LENGTH: +		{  			/* Ditto */ -			nubus_get_rsrc_mem(&dev->iosize, &ent, 4); -			pr_info("    memory length: 0x%08lx\n", dev->iosize); +			u32 length; + +			nubus_get_rsrc_mem(&length, &ent, 4); +			pr_debug("    memory length: 0x%08x\n", length); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);  			break; +		}  		case NUBUS_RESID_FLAGS: -			dev->flags = ent.data; -			pr_info("    flags: 0x%06x\n", dev->flags); +			pr_debug("    flags: 0x%06x\n", ent.data); +			nubus_proc_add_rsrc(dir.procdir, &ent);  			break;  		case NUBUS_RESID_HWDEVID: -			dev->hwdevid = ent.data; -			pr_info("    hwdevid: 0x%06x\n", dev->hwdevid); +			pr_debug("    hwdevid: 0x%06x\n", ent.data); +			nubus_proc_add_rsrc(dir.procdir, &ent);  			break;  		default:  			/* Local/Private resources have their own  			   function */ -			nubus_show_private_resource(dev, &ent); +			nubus_get_private_resource(fres, dir.procdir, &ent);  		}  	} -	return dev; -} - -/* This is cool. */ -static int __init nubus_get_vidnames(struct nubus_board *board, -				     const struct nubus_dirent *parent) -{ -	struct nubus_dir dir; -	struct nubus_dirent ent; - -	/* FIXME: obviously we want to put this in a header file soon */ -	struct vidmode { -		u32 size; -		/* Don't know what this is yet */ -		u16 id; -		/* Longest one I've seen so far is 26 characters */ -		char name[32]; -	}; - -	pr_info("    video modes supported:\n"); -	nubus_get_subdir(parent, &dir); -	pr_debug("%s: parent is 0x%p, dir is 0x%p\n", -	         __func__, parent->base, dir.base); - -	while (nubus_readdir(&dir, &ent) != -1) { -		struct vidmode mode; -		u32 size; - -		/* First get the length */ -		nubus_get_rsrc_mem(&size, &ent, 4); - -		/* Now clobber the whole thing */ -		if (size > sizeof(mode) - 1) -			size = sizeof(mode) - 1; -		memset(&mode, 0, sizeof(mode)); -		nubus_get_rsrc_mem(&mode, &ent, size); -		pr_info("      %02X: (%02X) %s\n", ent.type, -			mode.id, mode.name); -	} -	return 0; +	return fres;  }  /* This is *really* cool. */  static int __init nubus_get_icon(struct nubus_board *board, +				 struct proc_dir_entry *procdir,  				 const struct nubus_dirent *ent)  {  	/* Should be 32x32 if my memory serves me correctly */ -	unsigned char icon[128]; -	int x, y; +	u32 icon[32]; +	int i;  	nubus_get_rsrc_mem(&icon, ent, 128); -	pr_info("    icon:\n"); - -	/* We should actually plot these somewhere in the framebuffer -	   init.  This is just to demonstrate that they do, in fact, -	   exist */ -	for (y = 0; y < 32; y++) { -		pr_info("      "); -		for (x = 0; x < 32; x++) { -			if (icon[y * 4 + x / 8] & (0x80 >> (x % 8))) -				pr_cont("*"); -			else -				pr_cont(" "); -		} -		pr_cont("\n"); -	} +	pr_debug("    icon:\n"); +	for (i = 0; i < 8; i++) +		pr_debug("        %08x %08x %08x %08x\n", +			icon[i * 4 + 0], icon[i * 4 + 1], +			icon[i * 4 + 2], icon[i * 4 + 3]); +	nubus_proc_add_rsrc_mem(procdir, ent, 128); +  	return 0;  }  static int __init nubus_get_vendorinfo(struct nubus_board *board, +				       struct proc_dir_entry *procdir,  				       const struct nubus_dirent *parent)  {  	struct nubus_dir dir; @@ -589,19 +610,20 @@ static int __init nubus_get_vendorinfo(struct nubus_board *board,  	static char *vendor_fields[6] = { "ID", "serial", "revision",  	                                  "part", "date", "unknown field" }; -	pr_info("    vendor info:\n"); +	pr_debug("    vendor info:\n");  	nubus_get_subdir(parent, &dir); -	pr_debug("%s: parent is 0x%p, dir is 0x%p\n", -	         __func__, parent->base, dir.base); +	dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);  	while (nubus_readdir(&dir, &ent) != -1) {  		char name[64]; +		unsigned int len;  		/* These are all strings, we think */ -		nubus_get_rsrc_str(name, &ent, 64); -		if (ent.type > 5) +		len = nubus_get_rsrc_str(name, &ent, sizeof(name)); +		if (ent.type < 1 || ent.type > 5)  			ent.type = 5; -		pr_info("    %s: %s\n", vendor_fields[ent.type - 1], name); +		pr_debug("    %s: %s\n", vendor_fields[ent.type - 1], name); +		nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);  	}  	return 0;  } @@ -612,9 +634,9 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot,  	struct nubus_dir dir;  	struct nubus_dirent ent; +	pr_debug("  Board resource 0x%02x:\n", parent->type);  	nubus_get_subdir(parent, &dir); -	pr_debug("%s: parent is 0x%p, dir is 0x%p\n", -	         __func__, parent->base, dir.base); +	dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);  	while (nubus_readdir(&dir, &ent) != -1) {  		switch (ent.type) { @@ -625,64 +647,81 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot,  			   useful except insofar as it tells us that  			   we really are looking at a board resource. */  			nubus_get_rsrc_mem(nbtdata, &ent, 8); -			pr_info("    type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", -			        nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); +			pr_debug("    type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", +				nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);  			if (nbtdata[0] != 1 || nbtdata[1] != 0 ||  			    nbtdata[2] != 0 || nbtdata[3] != 0) -				pr_err("this sResource is not a board resource!\n"); +				pr_err("Slot %X: sResource is not a board resource!\n", +				       slot); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);  			break;  		}  		case NUBUS_RESID_NAME: -			nubus_get_rsrc_str(board->name, &ent, 64); -			pr_info("    name: %s\n", board->name); +		{ +			unsigned int len; + +			len = nubus_get_rsrc_str(board->name, &ent, +						 sizeof(board->name)); +			pr_debug("    name: %s\n", board->name); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);  			break; +		}  		case NUBUS_RESID_ICON: -			nubus_get_icon(board, &ent); +			nubus_get_icon(board, dir.procdir, &ent);  			break;  		case NUBUS_RESID_BOARDID: -			pr_info("    board id: 0x%x\n", ent.data); +			pr_debug("    board id: 0x%x\n", ent.data); +			nubus_proc_add_rsrc(dir.procdir, &ent);  			break;  		case NUBUS_RESID_PRIMARYINIT: -			pr_info("    primary init offset: 0x%06x\n", ent.data); +			pr_debug("    primary init offset: 0x%06x\n", ent.data); +			nubus_proc_add_rsrc(dir.procdir, &ent);  			break;  		case NUBUS_RESID_VENDORINFO: -			nubus_get_vendorinfo(board, &ent); +			nubus_get_vendorinfo(board, dir.procdir, &ent);  			break;  		case NUBUS_RESID_FLAGS: -			pr_info("    flags: 0x%06x\n", ent.data); +			pr_debug("    flags: 0x%06x\n", ent.data); +			nubus_proc_add_rsrc(dir.procdir, &ent);  			break;  		case NUBUS_RESID_HWDEVID: -			pr_info("    hwdevid: 0x%06x\n", ent.data); +			pr_debug("    hwdevid: 0x%06x\n", ent.data); +			nubus_proc_add_rsrc(dir.procdir, &ent);  			break;  		case NUBUS_RESID_SECONDINIT: -			pr_info("    secondary init offset: 0x%06x\n", ent.data); +			pr_debug("    secondary init offset: 0x%06x\n", +				 ent.data); +			nubus_proc_add_rsrc(dir.procdir, &ent);  			break;  			/* WTF isn't this in the functional resources? */  		case NUBUS_RESID_VIDNAMES: -			nubus_get_vidnames(board, &ent); +			pr_debug("    vidnames directory offset: 0x%06x\n", +				ent.data); +			nubus_get_block_rsrc_dir(board, dir.procdir, &ent);  			break;  			/* Same goes for this */  		case NUBUS_RESID_VIDMODES: -			pr_info("    video mode parameter directory offset: 0x%06x\n", -			       ent.data); +			pr_debug("    video mode parameter directory offset: 0x%06x\n", +				ent.data); +			nubus_proc_add_rsrc(dir.procdir, &ent);  			break;  		default: -			pr_info("    unknown resource %02X, data 0x%06x\n", -			       ent.type, ent.data); +			pr_debug("    unknown resource 0x%02x, data 0x%06x\n", +				ent.type, ent.data); +			nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);  		}  	}  	return 0;  } -/* Add a board (might be many devices) to the list */ -static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) +static void __init nubus_add_board(int slot, int bytelanes)  {  	struct nubus_board *board; -	struct nubus_board **boardp;  	unsigned char *rp;  	unsigned long dpat;  	struct nubus_dir dir;  	struct nubus_dirent ent; +	int prev_resid = -1;  	/* Move to the start of the format block */  	rp = nubus_rom_addr(slot); @@ -690,19 +729,19 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)  	/* Actually we should probably panic if this fails */  	if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL) -		return NULL; +		return;  	board->fblock = rp;  	/* Dump the format block for debugging purposes */  	pr_debug("Slot %X, format block at 0x%p:\n", slot, rp); +	pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); +	pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); +	pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));  	pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));  	pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));  	pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));  	pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));  	pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes)); -	pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); -	pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); -	pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));  	rp = board->fblock;  	board->slot = slot; @@ -722,10 +761,10 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)  	/* Directory offset should be small and negative... */  	if (!(board->doffset & 0x00FF0000)) -		pr_warn("Dodgy doffset!\n"); +		pr_warn("Slot %X: Dodgy doffset!\n", slot);  	dpat = nubus_get_rom(&rp, 4, bytelanes);  	if (dpat != NUBUS_TEST_PATTERN) -		pr_warn("Wrong test pattern %08lx!\n", dpat); +		pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat);  	/*  	 *	I wonder how the CRC is meant to work - @@ -742,53 +781,52 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)  	nubus_get_root_dir(board, &dir);  	/* We're ready to rock */ -	pr_info("Slot %X:\n", slot); +	pr_debug("Slot %X resources:\n", slot);  	/* Each slot should have one board resource and any number of -	   functional resources.  So we'll fill in some fields in the -	   struct nubus_board from the board resource, then walk down -	   the list of functional resources, spinning out a nubus_dev -	   for each of them. */ +	 * functional resources.  So we'll fill in some fields in the +	 * struct nubus_board from the board resource, then walk down +	 * the list of functional resources, spinning out a nubus_rsrc +	 * for each of them. +	 */  	if (nubus_readdir(&dir, &ent) == -1) {  		/* We can't have this! */ -		pr_err("Board resource not found!\n"); -		return NULL; -	} else { -		pr_info("  Board resource:\n"); -		nubus_get_board_resource(board, slot, &ent); +		pr_err("Slot %X: Board resource not found!\n", slot); +		kfree(board); +		return;  	} +	if (ent.type < 1 || ent.type > 127) +		pr_warn("Slot %X: Board resource ID is invalid!\n", slot); + +	board->procdir = nubus_proc_add_board(board); + +	nubus_get_board_resource(board, slot, &ent); +  	while (nubus_readdir(&dir, &ent) != -1) { -		struct nubus_dev *dev; -		struct nubus_dev **devp; +		struct nubus_rsrc *fres; -		dev = nubus_get_functional_resource(board, slot, &ent); -		if (dev == NULL) +		fres = nubus_get_functional_resource(board, slot, &ent); +		if (fres == NULL)  			continue; -		/* We zeroed this out above */ -		if (board->first_dev == NULL) -			board->first_dev = dev; +		/* Resources should appear in ascending ID order. This sanity +		 * check prevents duplicate resource IDs. +		 */ +		if (fres->resid <= prev_resid) { +			kfree(fres); +			continue; +		} +		prev_resid = fres->resid; -		/* Put it on the global NuBus device chain. Keep entries in order. */ -		for (devp = &nubus_devices; *devp != NULL; -		     devp = &((*devp)->next)) -			/* spin */; -		*devp = dev; -		dev->next = NULL; +		list_add_tail(&fres->list, &nubus_func_rsrcs);  	} -	/* Put it on the global NuBus board chain. Keep entries in order. */ -	for (boardp = &nubus_boards; *boardp != NULL; -	     boardp = &((*boardp)->next)) -		/* spin */; -	*boardp = board; -	board->next = NULL; - -	return board; +	if (nubus_device_register(board)) +		put_device(&board->dev);  } -void __init nubus_probe_slot(int slot) +static void __init nubus_probe_slot(int slot)  {  	unsigned char dp;  	unsigned char *rp; @@ -796,11 +834,8 @@ void __init nubus_probe_slot(int slot)  	rp = nubus_rom_addr(slot);  	for (i = 4; i; i--) { -		int card_present; -  		rp--; -		card_present = hwreg_present(rp); -		if (!card_present) +		if (!hwreg_present(rp))  			continue;  		dp = *rp; @@ -822,10 +857,11 @@ void __init nubus_probe_slot(int slot)  	}  } -void __init nubus_scan_bus(void) +static void __init nubus_scan_bus(void)  {  	int slot; +	pr_info("NuBus: Scanning NuBus slots.\n");  	for (slot = 9; slot < 15; slot++) {  		nubus_probe_slot(slot);  	} @@ -833,14 +869,16 @@ void __init nubus_scan_bus(void)  static int __init nubus_init(void)  { +	int err; +  	if (!MACH_IS_MAC)  		return 0; -	pr_info("NuBus: Scanning NuBus slots.\n"); -	nubus_devices = NULL; -	nubus_boards = NULL; -	nubus_scan_bus();  	nubus_proc_init(); +	err = nubus_bus_register(); +	if (err) +		return err; +	nubus_scan_bus();  	return 0;  } |