Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 576c352e authored by David S. Miller's avatar David S. Miller Committed by David S. Miller
Browse files

[SBUS]: Rewrite and plug into of_device framework.



I severely apologize, I was still learning how to program
in C when I wrote this stuff 10 years ago...

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fd531431
Loading
Loading
Loading
Loading
+85 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@
#include <asm/io.h>
#include <asm/vaddrs.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/sbus.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/dma.h>
@@ -458,6 +460,89 @@ void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg,
{
	printk("sbus_dma_sync_sg_for_device: not implemented yet\n");
}

/* Support code for sbus_init().  */
/*
 * XXX This functions appears to be a distorted version of
 * prom_sbus_ranges_init(), with all sun4d stuff cut away.
 * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
 */
/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */
void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
{
	int parent_node = pn->node;

	if (sparc_cpu_model == sun4d) {
		struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
		int num_iounit_ranges, len;

		len = prom_getproperty(parent_node, "ranges",
				       (char *) iounit_ranges,
				       sizeof (iounit_ranges));
		if (len != -1) {
			num_iounit_ranges =
				(len / sizeof(struct linux_prom_ranges));
			prom_adjust_ranges(sbus->sbus_ranges,
					   sbus->num_sbus_ranges,
					   iounit_ranges, num_iounit_ranges);
		}
	}
}

void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp)
{
	struct device_node *parent = dp->parent;

	if (sparc_cpu_model != sun4d &&
	    parent != NULL &&
	    !strcmp(parent->name, "iommu")) {
		extern void iommu_init(int iommu_node, struct sbus_bus *sbus);

		iommu_init(parent->node, sbus);
	}

	if (sparc_cpu_model == sun4d) {
		extern void iounit_init(int sbi_node, int iounit_node,
					struct sbus_bus *sbus);

		iounit_init(dp->node, parent->node, sbus);
	}
}

void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
{
	if (sparc_cpu_model == sun4d) {
		struct device_node *parent = dp->parent;

		sbus->devid = of_getintprop_default(parent, "device-id", 0);
		sbus->board = of_getintprop_default(parent, "board#", 0);
	}
}

int __init sbus_arch_preinit(void)
{
	extern void register_proc_sparc_ioport(void);

	register_proc_sparc_ioport();

#ifdef CONFIG_SUN4
	{
		extern void sun4_dvma_init(void);
		sun4_dvma_init();
	}
	return 1;
#else
	return 0;
#endif
}

void __init sbus_arch_postinit(void)
{
	if (sparc_cpu_model == sun4d) {
		extern void sun4d_init_sbi_irq(void);
		sun4d_init_sbi_irq();
	}
}
#endif /* CONFIG_SBUS */

#ifdef CONFIG_PCI
+30 −1
Original line number Diff line number Diff line
@@ -1099,7 +1099,7 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
}

/* Boot time initialization. */
void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
{
	struct linux_prom64_registers *pr;
	struct device_node *dp;
@@ -1247,3 +1247,32 @@ void sbus_fill_device_irq(struct sbus_dev *sdev)
		sdev->irqs[0] =	sbus_build_irq(sdev->bus, pri);
	}
}

void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
{
}

void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp)
{
	sbus_iommu_init(dp->node, sbus);
}

void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
{
}

int __init sbus_arch_preinit(void)
{
	return 0;
}

void __init sbus_arch_postinit(void)
{
	extern void firetruck_init(void);
	extern void auxio_probe(void);
	extern void clock_probe(void);

	firetruck_init();
	auxio_probe();
	clock_probe();
}
+139 −310
Original line number Diff line number Diff line
@@ -13,32 +13,29 @@
#include <asm/sbus.h>
#include <asm/dma.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/bpp.h>
#include <asm/irq.h>

struct sbus_bus *sbus_root;

#ifdef CONFIG_PCI
extern int pcic_present(void);
#endif

static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev)
{
	unsigned long address, base;
	unsigned long base;
	void *pval;
	int len;

	sdev->prom_node = prom_node;
	prom_getstring(prom_node, "name",
		       sdev->prom_name, sizeof(sdev->prom_name));
	address = prom_getint(prom_node, "address");
	len = prom_getproperty(prom_node, "reg",
			       (char *) sdev->reg_addrs,
			       sizeof(sdev->reg_addrs));
	sdev->prom_node = dp->node;
	strcpy(sdev->prom_name, dp->name);

	pval = of_get_property(dp, "reg", &len);
	sdev->num_registers = 0;
	if (len != -1) {
	if (pval) {
		memcpy(sdev->reg_addrs, pval, len);

		sdev->num_registers =
			len / sizeof(struct linux_prom_registers);
		sdev->ranges_applied = 0;

		base = (unsigned long) sdev->reg_addrs[0].phys_addr;

@@ -49,97 +46,43 @@ static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
			sdev->slot = sdev->reg_addrs[0].which_io;
	}

	len = prom_getproperty(prom_node, "ranges",
			       (char *)sdev->device_ranges,
			       sizeof(sdev->device_ranges));
	pval = of_get_property(dp, "ranges", &len);
	sdev->num_device_ranges = 0;
	if (len != -1)
	if (pval) {
		memcpy(sdev->device_ranges, pval, len);
		sdev->num_device_ranges =
			len / sizeof(struct linux_prom_ranges);
	}

	sbus_fill_device_irq(sdev);
}

/* This routine gets called from whoever needs the sbus first, to scan
 * the SBus device tree.  Currently it just prints out the devices
 * found on the bus and builds trees of SBUS structs and attached
 * devices.
 */
	sdev->ofdev.node = dp;
	if (sdev->parent)
		sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev;
	else
		sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev;
	sdev->ofdev.dev.bus = &sbus_bus_type;
	strcpy(sdev->ofdev.dev.bus_id, dp->path_component_name);

extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus);
void sun4_init(void);
#ifdef CONFIG_SUN_AUXIO
extern void auxio_probe(void);
#endif

static void __init sbus_do_child_siblings(int start_node,
					  struct sbus_dev *child,
					  struct sbus_dev *parent,
					  struct sbus_bus *sbus)
{
	struct sbus_dev *this_dev = child;
	int this_node = start_node;

	/* Child already filled in, just need to traverse siblings. */
	child->child = NULL;
	child->parent = parent;
	while((this_node = prom_getsibling(this_node)) != 0) {
		this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
		this_dev = this_dev->next;
		this_dev->next = NULL;
		this_dev->parent = parent;

		this_dev->bus = sbus;
		fill_sbus_device(this_node, this_dev);

		if(prom_getchild(this_node)) {
			this_dev->child = kmalloc(sizeof(struct sbus_dev),
						  GFP_ATOMIC);
			this_dev->child->bus = sbus;
			this_dev->child->next = NULL;
			fill_sbus_device(prom_getchild(this_node), this_dev->child);
			sbus_do_child_siblings(prom_getchild(this_node),
					       this_dev->child, this_dev, sbus);
		} else {
			this_dev->child = NULL;
		}
	}
	if (of_device_register(&sdev->ofdev) != 0)
		printk(KERN_DEBUG "sbus: device registration error for %s!\n",
		       sdev->ofdev.dev.bus_id);
}

/*
 * XXX This functions appears to be a distorted version of
 * prom_sbus_ranges_init(), with all sun4d stuff cut away.
 * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
 */
/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */

static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus)
static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus)
{
	void *pval;
	int len;

	len = prom_getproperty(sbus->prom_node, "ranges",
			       (char *) sbus->sbus_ranges,
			       sizeof(sbus->sbus_ranges));
	if (len == -1 || len == 0) {
	pval = of_get_property(dp, "ranges", &len);
	sbus->num_sbus_ranges = 0;
		return;
	}
	sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges);
#ifdef CONFIG_SPARC32
	if (sparc_cpu_model == sun4d) {
		struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
		int num_iounit_ranges;

		len = prom_getproperty(parent_node, "ranges",
				       (char *) iounit_ranges,
				       sizeof (iounit_ranges));
		if (len != -1) {
			num_iounit_ranges = (len/sizeof(struct linux_prom_ranges));
			prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges);
		}
	if (pval) {
		memcpy(sbus->sbus_ranges, pval, len);
		sbus->num_sbus_ranges =
			len / sizeof(struct linux_prom_ranges);

		sbus_arch_bus_ranges_init(dp->parent, sbus);
	}
#endif
}

static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
@@ -217,241 +160,127 @@ static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev)
	}
}

extern void register_proc_sparc_ioport(void);
extern void firetruck_init(void);
/* We preserve the "probe order" of these bus and device lists to give
 * the same ordering as the old code.
 */
static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root)
{
	while (*root)
		root = &(*root)->next;
	*root = sbus;
	sbus->next = NULL;
}

#ifdef CONFIG_SUN4
extern void sun4_dvma_init(void);
#endif
static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root)
{
	while (*root)
		root = &(*root)->next;
	*root = sdev;
	sdev->next = NULL;
}

static int __init sbus_init(void)
static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus)
{
	int nd, this_sbus, sbus_devs, topnd, iommund;
	unsigned int sbus_clock;
	struct sbus_bus *sbus;
	struct sbus_dev *this_dev;
	int num_sbus = 0;  /* How many did we find? */
	dp = dp->child;
	while (dp) {
		struct sbus_dev *sdev;

#ifdef CONFIG_SPARC32
	register_proc_sparc_ioport();
#endif
		sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
		if (sdev) {
			sdev_insert(sdev, &parent->child);

#ifdef CONFIG_SUN4
	sun4_dvma_init();
	return 0;
#endif

	topnd = prom_getchild(prom_root_node);
	
	/* Finding the first sbus is a special case... */
	iommund = 0;
	if(sparc_cpu_model == sun4u) {
		nd = prom_searchsiblings(topnd, "sbus");
		if(nd == 0) {
#ifdef CONFIG_PCI
			if (!pcic_present()) {
				prom_printf("Neither SBUS nor PCI found.\n");
				prom_halt();
			} else {
#ifdef CONFIG_SPARC64
				firetruck_init();
#endif
			}
			return 0;
#else
			prom_printf("YEEE, UltraSparc sbus not found\n");
			prom_halt();
#endif
		}
	} else if(sparc_cpu_model == sun4d) {
		if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 ||
		   (nd = prom_getchild(iommund)) == 0 ||
		   (nd = prom_searchsiblings(nd, "sbi")) == 0) {
		   	panic("sbi not found");
		}
	} else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) {
		if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 ||
		   (nd = prom_getchild(iommund)) == 0 ||
		   (nd = prom_searchsiblings(nd, "sbus")) == 0) {
#ifdef CONFIG_PCI
                        if (!pcic_present()) {
                                prom_printf("Neither SBUS nor PCI found.\n");
                                prom_halt();
			sdev->bus = sbus;
			sdev->parent = parent;

			fill_sbus_device(dp, sdev);

			walk_children(dp, sdev, sbus);
		}
                        return 0;
#else
			/* No reason to run further - the data access trap will occur. */
			panic("sbus not found");
#endif
		dp = dp->sibling;
	}
}

	/* Ok, we've found the first one, allocate first SBus struct
	 * and place in chain.
	 */
	sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
	sbus->next = NULL;
	sbus->prom_node = nd;
	this_sbus = nd;
static void __init build_one_sbus(struct device_node *dp, int num_sbus)
{
	struct sbus_bus *sbus;
	unsigned int sbus_clock;
	struct device_node *dev_dp;

	if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d)
		iommu_init(iommund, sbus);
	sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
	if (!sbus)
		return;

	/* Loop until we find no more SBUS's */
	while(this_sbus) {
#ifdef CONFIG_SPARC64
		/* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
		if(sparc_cpu_model == sun4u) {
			extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus);
	sbus_insert(sbus, &sbus_root);
	sbus->prom_node = dp->node;

			sbus_iommu_init(this_sbus, sbus);
		}
#endif /* CONFIG_SPARC64 */
	sbus_setup_iommu(sbus, dp);

#ifdef CONFIG_SPARC32
		if (sparc_cpu_model == sun4d)
			iounit_init(this_sbus, iommund, sbus);
#endif /* CONFIG_SPARC32 */
	printk("sbus%d: ", num_sbus);
		sbus_clock = prom_getint(this_sbus, "clock-frequency");
		if(sbus_clock == -1)
			sbus_clock = (25*1000*1000);

	sbus_clock = of_getintprop_default(dp, "clock-frequency",
					   (25*1000*1000));
	sbus->clock_freq = sbus_clock;

	printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000),
	       (int) (((sbus_clock/1000)%1000 != 0) ? 
		      (((sbus_clock/1000)%1000) + 1000) : 0));

		prom_getstring(this_sbus, "name",
			       sbus->prom_name, sizeof(sbus->prom_name));
		sbus->clock_freq = sbus_clock;
#ifdef CONFIG_SPARC32
		if (sparc_cpu_model == sun4d) {
			sbus->devid = prom_getint(iommund, "device-id");
			sbus->board = prom_getint(iommund, "board#");
		}
#endif
	strcpy(sbus->prom_name, dp->name);

		sbus_bus_ranges_init(iommund, sbus);
	sbus_setup_arch_props(sbus, dp);

		sbus_devs = prom_getchild(this_sbus);
		if (!sbus_devs) {
			sbus->devices = NULL;
			goto next_bus;
		}
	sbus_bus_ranges_init(dp, sbus);

		sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);

		this_dev = sbus->devices;
		this_dev->next = NULL;

		this_dev->bus = sbus;
		this_dev->parent = NULL;
		fill_sbus_device(sbus_devs, this_dev);

		/* Should we traverse for children? */
		if(prom_getchild(sbus_devs)) {
			/* Allocate device node */
			this_dev->child = kmalloc(sizeof(struct sbus_dev),
						  GFP_ATOMIC);
			/* Fill it */
			this_dev->child->bus = sbus;
			this_dev->child->next = NULL;
			fill_sbus_device(prom_getchild(sbus_devs),
					 this_dev->child);
			sbus_do_child_siblings(prom_getchild(sbus_devs),
					       this_dev->child,
					       this_dev,
					       sbus);
		} else {
			this_dev->child = NULL;
		}
	sbus->ofdev.node = dp;
	sbus->ofdev.dev.parent = NULL;
	sbus->ofdev.dev.bus = &sbus_bus_type;
	strcpy(sbus->ofdev.dev.bus_id, dp->path_component_name);

		while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
			/* Allocate device node */
			this_dev->next = kmalloc(sizeof(struct sbus_dev),
						 GFP_ATOMIC);
			this_dev = this_dev->next;
			this_dev->next = NULL;

			/* Fill it */
			this_dev->bus = sbus;
			this_dev->parent = NULL;
			fill_sbus_device(sbus_devs, this_dev);

			/* Is there a child node hanging off of us? */
			if(prom_getchild(sbus_devs)) {
				/* Get new device struct */
				this_dev->child = kmalloc(sizeof(struct sbus_dev),
							  GFP_ATOMIC);
				/* Fill it */
				this_dev->child->bus = sbus;
				this_dev->child->next = NULL;
				fill_sbus_device(prom_getchild(sbus_devs),
						 this_dev->child);
				sbus_do_child_siblings(prom_getchild(sbus_devs),
						       this_dev->child,
						       this_dev,
						       sbus);
			} else {
				this_dev->child = NULL;
	if (of_device_register(&sbus->ofdev) != 0)
		printk(KERN_DEBUG "sbus: device registration error for %s!\n",
		       sbus->ofdev.dev.bus_id);

	dev_dp = dp->child;
	while (dev_dp) {
		struct sbus_dev *sdev;

		sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
		if (sdev) {
			sdev_insert(sdev, &sbus->devices);

			sdev->bus = sbus;
			sdev->parent = NULL;
			fill_sbus_device(dev_dp, sdev);

			walk_children(dev_dp, sdev, sbus);
		}
		dev_dp = dev_dp->sibling;
	}

		/* Walk all devices and apply parent ranges. */
	sbus_fixup_all_regs(sbus->devices);

	dvma_init(sbus);
	next_bus:
		num_sbus++;
		if(sparc_cpu_model == sun4u) {
			this_sbus = prom_getsibling(this_sbus);
			if(!this_sbus)
				break;
			this_sbus = prom_searchsiblings(this_sbus, "sbus");
		} else if(sparc_cpu_model == sun4d) {
			iommund = prom_getsibling(iommund);
			if(!iommund)
				break;
			iommund = prom_searchsiblings(iommund, "io-unit");
			if(!iommund)
				break;
			this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi");
		} else {
			this_sbus = prom_getsibling(this_sbus);
			if(!this_sbus)
				break;
			this_sbus = prom_searchsiblings(this_sbus, "sbus");
}
		if(this_sbus) {
			sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
			sbus = sbus->next;
			sbus->next = NULL;
			sbus->prom_node = this_sbus;
		} else {
			break;
		}
	} /* while(this_sbus) */

	if (sparc_cpu_model == sun4d) {
		extern void sun4d_init_sbi_irq(void);
		sun4d_init_sbi_irq();
	}
static int __init sbus_init(void)
{
	struct device_node *dp;
	const char *sbus_name = "sbus";
	int num_sbus = 0;

	if (sbus_arch_preinit())
		return 0;

	if (sparc_cpu_model == sun4d)
		sbus_name = "sbi";

	for_each_node_by_name(dp, sbus_name) {
		build_one_sbus(dp, num_sbus);
		num_sbus++;

#ifdef CONFIG_SPARC64
	if (sparc_cpu_model == sun4u) {
		firetruck_init();
	}
#endif
#ifdef CONFIG_SUN_AUXIO
	if (sparc_cpu_model == sun4u)
		auxio_probe ();
#endif
#ifdef CONFIG_SPARC64
	if (sparc_cpu_model == sun4u) {
		extern void clock_probe(void);

		clock_probe();
	}
#endif

	sbus_arch_postinit();

	return 0;
}
+19 −8
Original line number Diff line number Diff line
@@ -11,7 +11,8 @@
#include <linux/ioport.h>

#include <asm/oplib.h>
/* #include <asm/iommu.h> */ /* Unused since we use opaque iommu (|io-unit) */
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/scatterlist.h>

/* We scan which devices are on the SBus using the PROM node device
@@ -42,18 +43,19 @@ struct sbus_bus;

/* Linux SBUS device tables */
struct sbus_dev {
	struct sbus_bus	*bus;       /* Back ptr to sbus */
	struct sbus_dev	*next;      /* next device on this SBus or null */
	struct sbus_dev	*child;     /* For ledma and espdma on sun4m */
	struct sbus_dev	*parent;    /* Parent device if not toplevel */
	int prom_node;              /* PROM device tree node for this device */
	char prom_name[64];         /* PROM device name */
	struct of_device	ofdev;
	struct sbus_bus		*bus;
	struct sbus_dev		*next;
	struct sbus_dev		*child;
	struct sbus_dev		*parent;
	int prom_node;	
	char prom_name[64];
	int slot;

	struct resource resource[PROMREG_MAX];

	struct linux_prom_registers reg_addrs[PROMREG_MAX];
	int num_registers, ranges_applied;
	int num_registers;

	struct linux_prom_ranges device_ranges[PROMREG_MAX];
	int num_device_ranges;
@@ -61,9 +63,11 @@ struct sbus_dev {
	unsigned int irqs[4];
	int num_irqs;
};
#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev)

/* This struct describes the SBus(s) found on this machine. */
struct sbus_bus {
	struct of_device	ofdev;
	void			*iommu;		/* Opaque IOMMU cookie */
	struct sbus_dev		*devices;	/* Link to devices on this SBus */
	struct sbus_bus		*next;		/* next SBus, if more than one SBus */
@@ -77,6 +81,7 @@ struct sbus_bus {
	int devid;
	int board;
};
#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev)

extern struct sbus_bus *sbus_root;

@@ -140,4 +145,10 @@ extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *,
BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int)
#define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint)

extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *);
extern int sbus_arch_preinit(void);
extern void sbus_arch_postinit(void);

#endif /* !(_SPARC_SBUS_H) */
+20 −8
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@
#include <linux/ioport.h>

#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/iommu.h>
#include <asm/scatterlist.h>

@@ -42,18 +44,19 @@ struct sbus_bus;

/* Linux SBUS device tables */
struct sbus_dev {
	struct sbus_bus *bus;	/* Our toplevel parent SBUS	*/
	struct sbus_dev *next;	/* Chain of siblings		*/
	struct sbus_dev *child;	/* Chain of children		*/
	struct sbus_dev *parent;/* Parent device if not toplevel*/
	int prom_node;		/* OBP node of this device	*/
	char prom_name[64];	/* OBP device name property	*/
	int slot;		/* SBUS slot number		*/
	struct of_device	ofdev;
	struct sbus_bus		*bus;
	struct sbus_dev		*next;
	struct sbus_dev		*child;
	struct sbus_dev		*parent;
	int prom_node;	
	char prom_name[64];
	int slot;

	struct resource resource[PROMREG_MAX];

	struct linux_prom_registers reg_addrs[PROMREG_MAX];
	int num_registers, ranges_applied;
	int num_registers;

	struct linux_prom_ranges device_ranges[PROMREG_MAX];
	int num_device_ranges;
@@ -61,9 +64,11 @@ struct sbus_dev {
	unsigned int irqs[4];
	int num_irqs;
};
#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev)

/* This struct describes the SBus(s) found on this machine. */
struct sbus_bus {
	struct of_device	ofdev;
	void			*iommu;		/* Opaque IOMMU cookie	*/
	struct sbus_dev		*devices;	/* Tree of SBUS devices	*/
	struct sbus_bus		*next;		/* Next SBUS in system	*/
@@ -77,6 +82,7 @@ struct sbus_bus {
	int portid;
	void *starfire_cookie;
};
#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev)

extern struct sbus_bus *sbus_root;

@@ -120,4 +126,10 @@ extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, in
#define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu
extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int);

extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *);
extern int sbus_arch_preinit(void);
extern void sbus_arch_postinit(void);

#endif /* !(_SPARC64_SBUS_H) */