/* * 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, ®) != 0) return 0; if ((reg & 0xff) != SBIC_ASR_INT) return 0; return 1; }
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; }
/* * 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; }
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; }