/* * 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; }
/* * 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; }