コード例 #1
0
static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
{
	unsigned long address, base;
	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));
	if (len == -1) {
		sdev->num_registers = 0;
		goto no_regs;
	}

	if (len % sizeof(struct linux_prom_registers)) {
		prom_printf("fill_sbus_device: proplen for regs of %s "
			    " was %d, need multiple of %d\n",
			    sdev->prom_name, len,
			    (int) sizeof(struct linux_prom_registers));
		prom_halt();
	}
	if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) {
		prom_printf("fill_sbus_device: Too many register properties "
			    "for device %s, len=%d\n",
			    sdev->prom_name, len);
		prom_halt();
	}
	sdev->num_registers = len / sizeof(struct linux_prom_registers);
	sdev->ranges_applied = 0;

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

	/* Compute the slot number. */
	if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) {
		sdev->slot = sbus_dev_slot(base);
	} else {
		sdev->slot = sdev->reg_addrs[0].which_io;
	}

no_regs:
	len = prom_getproperty(prom_node, "ranges",
			       (char *)sdev->device_ranges,
			       sizeof(sdev->device_ranges));
	if (len == -1) {
		sdev->num_device_ranges = 0;
		goto no_ranges;
	}
	if (len % sizeof(struct linux_prom_ranges)) {
		prom_printf("fill_sbus_device: proplen for ranges of %s "
			    " was %d, need multiple of %d\n",
			    sdev->prom_name, len,
			    (int) sizeof(struct linux_prom_ranges));
		prom_halt();
	}
	if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) {
		prom_printf("fill_sbus_device: Too many range properties "
			    "for device %s, len=%d\n",
			    sdev->prom_name, len);
		prom_halt();
	}
	sdev->num_device_ranges =
		len / sizeof(struct linux_prom_ranges);

no_ranges:
	/* XXX Unfortunately, IRQ issues are very arch specific.
	 * XXX Pull this crud out into an arch specific area
	 * XXX at some point. -DaveM
	 */
#ifdef __sparc_v9__
	len = prom_getproperty(prom_node, "interrupts",
			       (char *) irqs, sizeof(irqs));
	if (len == -1 || len == 0) {
		sdev->irqs[0] = 0;
		sdev->num_irqs = 0;
	} else {
		unsigned int pri = irqs[0].pri;

		sdev->num_irqs = 1;
		if (pri < 0x20)
			pri += sdev->slot * 8;

		sdev->irqs[0] =	sbus_build_irq(sdev->bus, pri);
	}
#else
	len = prom_getproperty(prom_node, "intr",
			       (char *)irqs, sizeof(irqs));
	if (len == -1)
		len = 0;
	sdev->num_irqs = len / 8;
	if (sdev->num_irqs == 0) {
		sdev->irqs[0] = 0;
	} else if (sparc_cpu_model == sun4d) {
		extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);

		for (len = 0; len < sdev->num_irqs; len++)
			sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
	} else {
		for (len = 0; len < sdev->num_irqs; len++)
			sdev->irqs[len] = irqs[len].pri;
	}
#endif /* !__sparc_v9__ */
}
コード例 #2
0
__initfunc(static void
fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev))
{
	int grrr, len;
	unsigned long dev_base_addr, base;

	sbus_dev->prom_node = nd;
	prom_getstring(nd, "name", lbuf, sizeof(lbuf));
	strcpy(sbus_dev->prom_name, lbuf);

	dev_base_addr = prom_getint(nd, "address");
	if(dev_base_addr != -1)
		sbus_dev->sbus_addr = dev_base_addr;

	len = prom_getproperty(nd, "reg", (void *) sbus_dev->reg_addrs,
			       sizeof(sbus_dev->reg_addrs));
	if(len == -1)
		goto no_regs;
	if(len%sizeof(struct linux_prom_registers)) {
		prom_printf("WHOOPS:  proplen for %s was %d, need multiple of %d\n",
		       sbus_dev->prom_name, len,
		       (int) sizeof(struct linux_prom_registers));
		panic("fill_sbus_device");
	}
	sbus_dev->num_registers = (len/sizeof(struct linux_prom_registers));
	sbus_dev->ranges_applied = 0;

	base = (unsigned long) sbus_dev->reg_addrs[0].phys_addr;
	if(base>=SUN_SBUS_BVADDR ||
	   (sparc_cpu_model != sun4c &&
	   sparc_cpu_model != sun4)) {
		/* Ahh, we can determine the slot and offset */
		if(sparc_cpu_model == sun4u) {
			/* A bit tricky on the SYSIO. */
			sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
			sbus_dev->offset = sbus_dev_offset(base);
		} else if (sparc_cpu_model == sun4d) {
			sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
			sbus_dev->offset = base;
		} else {
			sbus_dev->slot = sbus_dev_slot(base);
			sbus_dev->offset = sbus_dev_offset(base);
		}
	} else {   /* Grrr, gotta do calculations to fix things up */
		sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
		sbus_dev->offset = base;
		sbus_dev->reg_addrs[0].phys_addr = 
			sbus_devaddr(sbus_dev->slot, base);
		for(grrr=1; grrr<sbus_dev->num_registers; grrr++) {
			base = (unsigned long) sbus_dev->reg_addrs[grrr].phys_addr;
			sbus_dev->reg_addrs[grrr].phys_addr =
				sbus_devaddr(sbus_dev->slot, base);
		}
		/* That surely sucked */
	}
	sbus_dev->sbus_addr = (unsigned long) sbus_dev->reg_addrs[0].phys_addr;
	if(len>(sizeof(struct linux_prom_registers)*PROMREG_MAX)) {
		prom_printf("WHOOPS:  I got too many register addresses for %s  len=%d\n",
		       sbus_dev->prom_name, len);
		panic("sbus device register overflow");
	}

no_regs:
	len = prom_getproperty(nd, "address", (void *) sbus_dev->sbus_vaddrs,
			       sizeof(sbus_dev->sbus_vaddrs));
	if(len == -1) len=0;
	if(len&3) {
		prom_printf("Grrr, I didn't get a multiple of 4 proplen "
		       "for device %s got %d\n", sbus_dev->prom_name, len);
		len=0;
	}
	sbus_dev->num_vaddrs = (len/4);

#ifdef __sparc_v9__  
	len = prom_getproperty(nd, "interrupts", (void *)irqs, sizeof(irqs));
	if((len == -1) || (len == 0)) {
		sbus_dev->irqs[0] = 0;
		sbus_dev->num_irqs = 0;
	} else {
		sbus_dev->num_irqs = 1;
		if (irqs[0].pri < 0x20)
			sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, 
					irqs[0].pri + (sbus_dev->slot * 8));
		else
			sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, 
					irqs[0].pri);
	}
#else
	len = prom_getproperty(nd, "intr", (void *)irqs, sizeof(irqs));
	if (len == -1) len=0;
	if (len&7) {
		prom_printf("Grrr, I didn't get a multiple of 8 proplen for "
			    "device %s got %d\n", sbus_dev->prom_name, len);
		len=0;
	}
	if (len > 4 * 8) {
		prom_printf("Device %s has more than 4 interrupts\n", sbus_dev->prom_name);
		len = 4 * 8;
	}
	sbus_dev->num_irqs=(len/8);
	if(sbus_dev->num_irqs == 0)
		sbus_dev->irqs[0]=0;
	else if (sparc_cpu_model != sun4d)
		for (len = 0; len < sbus_dev->num_irqs; len++)
			sbus_dev->irqs[len] = irqs[len].pri;
	else {
		extern unsigned int sun4d_build_irq(struct linux_sbus_device *sdev, int irq);
		
		for (len = 0; len < sbus_dev->num_irqs; len++)
			sbus_dev->irqs[len] = sun4d_build_irq(sbus_dev, irqs[len].pri);
	}
#endif

#ifdef DEBUG_FILL
#ifdef __sparc_v9__
	prom_printf("Found %s at SBUS slot %x offset %016lx ",
	       sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset);
	if (sbus_dev->irqs[0])
		prom_printf("irq %s\n", __irq_itoa(sbus_dev->irqs[0]));
	else
		prom_printf("\n");
	prom_printf("Base address %016lx\n", sbus_dev->sbus_addr);
#else
	prom_printf("Found %s at SBUS slot %x offset %08lx irq-level %d\n",
	       sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset,
	       sbus_dev->irqs[0]);
	prom_printf("Base address %08lx\n", sbus_dev->sbus_addr);
#endif
	prom_printf("REGISTERS: Probed %d register(s)\n", sbus_dev->num_registers);
	for(len=0; len<sbus_dev->num_registers; len++)
#ifdef __sparc_v9__
		prom_printf("Regs<%d> at address<%08lx> IO-space<%d> size<%d "
		       "bytes, %d words>\n", (int) len,
		       (unsigned long) sbus_dev->reg_addrs[len].phys_addr,
		       sbus_dev->reg_addrs[len].which_io,
		       sbus_dev->reg_addrs[len].reg_size,
		       (sbus_dev->reg_addrs[len].reg_size/4));
#else
		prom_printf("Regs<%d> at address<%016lx> IO-space<%d> size<%d "
		       "bytes, %d words>\n", (int) len,
		       (unsigned long) sbus_dev->reg_addrs[len].phys_addr,
		       sbus_dev->reg_addrs[len].which_io,
		       sbus_dev->reg_addrs[len].reg_size,
		       (sbus_dev->reg_addrs[len].reg_size/4));
#endif
#endif
}