Beispiel #1
0
/*
 * Match for SCSI devices on the onboard and GIO32 adapter WD33C93 chips
 */
int
wdsc_match(struct device *parent, void *vcf, void *aux)
{
	struct hpc_attach_args *haa = aux;
	struct cfdata *cf = vcf;
	vaddr_t reset, asr;
	uint32_t dummy;
	uint8_t reg;

	if (strcmp(haa->ha_name, cf->cf_driver->cd_name) != 0)
		return 0;

	reset = PHYS_TO_XKPHYS(haa->ha_sh + haa->ha_dmaoff +
	    haa->hpc_regs->scsi0_ctl, CCA_NC);
	if (guarded_read_4(reset, &dummy) != 0)
		return 0;
	*(volatile uint32_t *)reset = haa->hpc_regs->scsi_dmactl_reset;
	delay(1000);
	*(volatile uint32_t *)reset = 0x0;
	delay(1000);

	asr = PHYS_TO_XKPHYS(haa->ha_sh + haa->ha_devoff + 3, CCA_NC);
	if (guarded_read_1(asr, &reg) != 0)
		return 0;
	if ((reg & 0xff) != SBIC_ASR_INT)
		return 0;

	return 1;
}
Beispiel #2
0
uint32_t
imc_bus_error(uint32_t hwpend, struct trap_frame *tf)
{
	uint32_t cpustat, giostat;
	int quiet = 0;

	cpustat = imc_read(IMC_CPU_ERRSTAT);
	giostat = imc_read(IMC_GIO_ERRSTAT);

	switch (sys_config.system_type) {
	case SGI_IP28:
		/*
		 * R10000 speculative execution may attempt to access
		 * non-existing memory when in the kernel. We do not
		 * want to flood the console about those.
		 */
		if ((cpustat & IMC_CPU_ERRSTAT_ADDR) &&
		    IS_XKPHYS((vaddr_t)tf->pc))
			quiet = 1;
		/* This happens. No idea why. */
		if (cpustat == 0 && giostat == 0)
			quiet = 1;
		break;
	}

	if (quiet == 0) {
		printf("bus error:");
		if (cpustat != 0) {
			vaddr_t pc = tf->pc;
			uint32_t insn = 0xffffffff;

			if (tf->pc < 0)
				guarded_read_4(pc, &insn);
			else
				copyin((void *)pc, &insn, sizeof insn);

			printf(" cpu_stat %08x addr %08x pc %p insn %08x",
			    cpustat, imc_read(IMC_CPU_ERRADDR), pc, insn);
		}
		if (giostat != 0)
			printf(" gio_stat %08x addr %08x",
			    giostat, imc_read(IMC_GIO_ERRADDR));
		printf("\n");
	}

	if (cpustat != 0)
		imc_write(IMC_CPU_ERRSTAT, 0);
	if (giostat != 0)
		imc_write(IMC_GIO_ERRSTAT, 0);

	return hwpend;
}
Beispiel #3
0
/*
 * Try and figure out whether there is a device at the given slot address.
 */
uint32_t
gio_id(vaddr_t va, paddr_t pa, int maybe_gfx)
{
	uint32_t id32, mystery;
	uint16_t id16 = 0;
	uint8_t id8 = 0;

	/*
	 * First, attempt to read the address with various sizes.
	 *
	 * - GIO32 devices will only support reads from 32-bit aligned
	 *   addresses, in all sizes (at least for the ID register).
	 * - frame buffers will support aligned reads from any size at
	 *   any address, but will actually return the access width if
	 *   the slot is pipelined.
	 */

	if (guarded_read_4(va, &id32) != 0)
		return 0;

	/*
	 * If the address doesn't match a base slot address, then we are
	 * only probing for a light(4) frame buffer.
	 */

	if (pa != GIO_ADDR_GFX && pa != GIO_ADDR_EXP0 && pa != GIO_ADDR_EXP1) {
		if (maybe_gfx == 0)
			return 0;
		else {
			if (pa == LIGHT_ADDR_0 || pa == LIGHT_ADDR_1) {
				if (guarded_read_4(va + REX_PAGE1_SET +
				    REX_P1REG_XYOFFSET, &id32) != 0)
					return 0;
				if (id32 == 0x08000800)
					return GIO_PRODUCT_FAKEID_LIGHT;
			}
			return 0;
		}
	}

	/*
	 * GIO32 devices with a 32-bit ID register will not necessarily
	 * answer to addresses not aligned on 32 bit boundaries.
	 */

	if (guarded_read_2(va | 2, &id16) != 0 ||
	    guarded_read_1(va | 3, &id8) != 0) {
		if (GIO_PRODUCT_32BIT_ID(id32))
			return id32;
		else /* not a frame buffer anyway */
			return GIO_PRODUCT_PRODUCTID(id32);
	}

	/*
	 * Of course, GIO32 devices with a 8-bit ID register can use the
	 * other bytes in the first 32-bit word for other purposes.
	 */

	if ((id32 & 0xffff) == id16 && (id32 & 0xff) == id8) {
		if (GIO_PRODUCT_32BIT_ID(id32))
			return id32;
		else if (!GIO_PRODUCT_32BIT_ID(id8) && id8 != 0x00)
			return /*GIO_PRODUCT_PRODUCTID*/(id8);
	}

	/*
	 * If there is a frame buffer device, then either we have hit a
	 * device register (grtwo), or we did not fault because the slot
	 * is pipelined (newport).
	 * In the latter case, we attempt to probe a known register offset.
	 */

	if (maybe_gfx) {
		/*
		 * On (at least) Indy systems with newport graphics, the
		 * presence of a SCSI Expansion board (030-8133) in either
		 * slot will cause extra bits to be set in the topmost byte
		 * of the 32-bit access to the pipelined slot (i.e. the
		 * value of id32 is 0x18000004, not 0x00000004).
		 *
		 * This would prevent newport from being recognized
		 * properly.
		 *
		 * This behaviour seems to be specific to the SCSI board,
		 * since the E++ board does not trigger it. This would
		 * rule out an HPC1.x-specific cause.
		 * 
		 * We work around this by ignoring the topmost byte of id32
		 * from this point on, but it's ugly and isaish...
		 *
		 * Note that this is not necessary on Indigo 2 since this
		 * troublesome board can not be installed on such a system.
		 * Indigo are probably safe from this issues, for they can't
		 * use newport graphics; but the issue at hand might be
		 * HPC 1.x related, so better play safe.
		 */
		if (sys_config.system_type == SGI_IP20 ||
		    (sys_config.system_type == SGI_IP22 &&
		     sys_config.system_subtype != IP22_INDIGO2))
			id32 &= ~0xff000000;

		if (id32 != 4 || id16 != 2 || id8 != 1) {
			if (guarded_read_4(va + HQ2_MYSTERY, &mystery) == 0 &&
			    mystery == HQ2_MYSTERY_VALUE)
				return GIO_PRODUCT_FAKEID_GRTWO;
			else
				return 0;
		}

		/* could be newport(4) */
		if (pa == GIO_ADDR_GFX || pa == GIO_ADDR_EXP0) {
			va += NEWPORT_REX3_OFFSET;
			if (guarded_read_4(va, &id32) == 0 &&
			    guarded_read_2(va | 2, &id16) == 0 &&
			    guarded_read_1(va | 3, &id8) == 0) {
				if (id32 != 4 || id16 != 2 || id8 != 1)
					return GIO_PRODUCT_FAKEID_NEWPORT;
			}
		}

		return 0;
	}

	return 0;
}
Beispiel #4
0
uint32_t
imc_bus_error(uint32_t hwpend, struct trap_frame *tf)
{
	uint32_t cpustat, giostat;
	paddr_t cpuaddr, gioaddr;
	int cpuquiet = 0, gioquiet = 0;

	cpustat = imc_read(IMC_CPU_ERRSTAT);
	cpuaddr = imc_read(IMC_CPU_ERRADDR);
	giostat = imc_read(IMC_GIO_ERRSTAT);
	gioaddr = imc_read(IMC_GIO_ERRADDR);

	switch (sys_config.system_type) {
	case SGI_IP28:
		/*
		 * R10000 speculative execution may attempt to access
		 * non-existing memory when in the kernel. We do not
		 * want to flood the console about those.
		 */
		if (cpustat & IMC_CPU_ERRSTAT_ADDR) {
			if (IS_XKPHYS((vaddr_t)tf->pc))
				cpuquiet = 1;
		}
		if (giostat != 0) {
			/*
			 * Ignore speculative writes to interrupt controller
			 * registers.
			 */
			if ((giostat & IMC_ECC_ERRSTAT_FUW) &&
			    (gioaddr & ~0x3f) == INT2_IP22)
				gioquiet = 1;
			/* XXX is it wise to hide these? */
			if ((giostat & IMC_GIO_ERRSTAT_TMO) &&
			    !IS_GIO_ADDRESS(gioaddr))
				gioquiet = 1;
		}
		break;
	}

	if (cpustat != 0 && cpuquiet == 0) {
		vaddr_t pc = tf->pc;
		uint32_t insn = 0xffffffff;

		if (tf->pc < 0)
			guarded_read_4(pc, &insn);
		else
			copyin((void *)pc, &insn, sizeof insn);

		printf("bus error: cpu_stat %08x addr %08lx pc %p insn %08x\n",
		    cpustat, cpuaddr, (void *)pc, insn);
	}
	if (giostat != 0 && gioquiet == 0) {
		printf("bus error: gio_stat %08x addr %08lx\n",
		    giostat, gioaddr);
	}

	if (cpustat != 0)
		imc_write(IMC_CPU_ERRSTAT, 0);
	if (giostat != 0)
		imc_write(IMC_GIO_ERRSTAT, 0);

	return hwpend;
}