int gio_print_fb(void *aux, const char *pnp) { struct gio_attach_args *ga = aux; const char *fbname; if (pnp != NULL) { switch (ga->ga_product) { case GIO_PRODUCT_FAKEID_GRTWO: fbname = "grtwo"; break; case GIO_PRODUCT_FAKEID_LIGHT: fbname = "light"; break; case GIO_PRODUCT_FAKEID_NEWPORT: fbname = "newport"; break; default: if (GIO_PRODUCT_32BIT_ID(ga->ga_product) && GIO_PRODUCT_PRODUCTID(ga->ga_product) == GIO_PRODUCT_IMPACT) fbname = "impact"; else /* should never happen */ fbname = "framebuffer"; break; } printf("%s at %s", fbname, pnp); } printf(" addr 0x%lx", ga->ga_addr); return UNCONF; }
int gio_is_framebuffer_id(uint32_t id) { switch (id) { case GIO_PRODUCT_FAKEID_GRTWO: case GIO_PRODUCT_FAKEID_LIGHT: case GIO_PRODUCT_FAKEID_NEWPORT: return 1; default: if (GIO_PRODUCT_32BIT_ID(id) && GIO_PRODUCT_PRODUCTID(id) == GIO_PRODUCT_IMPACT) return 1; else return 0; } }
int giofb_cnattach() { struct gio_attach_args ga; ga.ga_addr = giofb_consaddr; ga.ga_iot = &imcbus_tag; ga.ga_ioh = PHYS_TO_XKPHYS(ga.ga_addr, CCA_NC); ga.ga_dmat = &imc_bus_dma_tag; ga.ga_slot = -1; ga.ga_product = giofb_consid; ga.ga_descr = NULL; switch (giofb_consid) { default: #if NIMPACT_GIO > 0 if (GIO_PRODUCT_32BIT_ID(giofb_consid) && GIO_PRODUCT_PRODUCTID(giofb_consid) == GIO_PRODUCT_IMPACT) { if (impact_gio_cnattach(&ga) == 0) return 0; } #endif break; case GIO_PRODUCT_FAKEID_GRTWO: #if NGRTWO > 0 if (grtwo_cnattach(&ga) == 0) return 0; #endif break; case GIO_PRODUCT_FAKEID_LIGHT: #if NLIGHT > 0 if (light_cnattach(&ga) == 0) return 0; #endif break; case GIO_PRODUCT_FAKEID_NEWPORT: #if NNEWPORT > 0 if (newport_cnattach(&ga) == 0) return 0; #endif break; } giofb_consaddr = 0; return ENXIO; }
static int giopci_match(struct device *parent, struct cfdata *match, void *aux) { struct gio_attach_args *ga = aux; int gprid; /* * I think that these cards are all GIO32-bis or GIO64. Thus * they work in either Indigo2/Challenge M or * Indy/Challenge S/Indigo R4k, according to form factor. However, * there are some exceptions (e.g. my Indigo R4k won't power * on with the Set Engineering card installed). */ if (mach_type != MACH_SGI_IP20 && mach_type != MACH_SGI_IP22) return (0); gprid = GIO_PRODUCT_PRODUCTID(ga->ga_product); if (gprid == PHOBOS_G100 || gprid == PHOBOS_G130 || gprid == PHOBOS_G160 || gprid == SETENG_GFE) return (1); return (0); }
int gio_print(void *aux, const char *pnp) { struct gio_attach_args *ga = aux; const char *descr; int product, revision; uint i; product = GIO_PRODUCT_PRODUCTID(ga->ga_product); if (GIO_PRODUCT_32BIT_ID(ga->ga_product)) revision = GIO_PRODUCT_REVISION(ga->ga_product); else revision = 0; descr = "unknown GIO card"; for (i = 0; gio_knowndevs[i].productid != 0; i++) { if (gio_knowndevs[i].productid == product) { descr = gio_knowndevs[i].product; break; } } if (pnp != NULL) { printf("%s", descr); if (ga->ga_product != -1) printf(" (product 0x%02x revision 0x%02x)", product, revision); printf(" at %s", pnp); } if (ga->ga_slot != -1) printf(" slot %d", ga->ga_slot); printf(" addr 0x%lx", ga->ga_addr); return UNCONF; }
int giofb_cnprobe() { struct gio_attach_args ga; uint32_t id; int i; int sys_type; switch (sys_config.system_type) { case SGI_IP20: sys_type = SGI_IP20; break; default: case SGI_IP22: case SGI_IP26: case SGI_IP28: sys_type = SGI_IP22; break; } for (i = 0; gfx_bases[i].base != 0; i++) { if (giofb_consaddr != 0 && gfx_bases[i].base != giofb_consaddr) continue; /* skip bases that don't apply to us */ if (gfx_bases[i].mach_type != sys_type) continue; if (gfx_bases[i].mach_subtype != -1 && gfx_bases[i].mach_subtype != sys_config.system_subtype) continue; ga.ga_addr = gfx_bases[i].base; ga.ga_iot = &imcbus_tag; ga.ga_ioh = PHYS_TO_XKPHYS(ga.ga_addr, CCA_NC); ga.ga_dmat = &imc_bus_dma_tag; ga.ga_slot = -1; ga.ga_descr = NULL; id = gio_id(ga.ga_ioh, ga.ga_addr, 1); if (!gio_is_framebuffer_id(id)) continue; ga.ga_product = giofb_consid = id; switch (id) { default: #if NIMPACT_GIO > 0 if (GIO_PRODUCT_32BIT_ID(id) && GIO_PRODUCT_PRODUCTID(id) == GIO_PRODUCT_IMPACT) { if (impact_gio_cnprobe(&ga) != 0) return 0; } #endif break; case GIO_PRODUCT_FAKEID_GRTWO: #if NGRTWO > 0 if (grtwo_cnprobe(&ga) != 0) return 0; #endif break; case GIO_PRODUCT_FAKEID_LIGHT: #if NLIGHT > 0 if (light_cnprobe(&ga) != 0) return 0; #endif break; case GIO_PRODUCT_FAKEID_NEWPORT: #if NNEWPORT > 0 if (newport_cnprobe(&ga) != 0) return 0; #endif break; } } return ENXIO; }
/* * 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; }
static void giopci_attach(struct device *parent, struct device *self, void *aux) { struct giopci_softc *sc = (void *)self; pci_chipset_tag_t pc = &sc->sc_pc; struct gio_attach_args *ga = aux; uint32_t pci_off, pci_len, arb; struct pcibus_attach_args pba; u_long m_start, m_end; #ifdef PCI_NETBSD_CONFIGURE extern int pci_conf_debug; pci_conf_debug = giopci_debug; #endif sc->sc_iot = ga->ga_iot; sc->sc_slot = ga->ga_slot; sc->sc_gprid = GIO_PRODUCT_PRODUCTID(ga->ga_product); if (mach_type == MACH_SGI_IP22 && mach_subtype == MACH_SGI_IP22_FULLHOUSE) arb = GIO_ARB_RT | GIO_ARB_MST | GIO_ARB_PIPE; else arb = GIO_ARB_RT | GIO_ARB_MST; if (gio_arb_config(ga->ga_slot, arb)) { printf(": failed to configure GIO bus arbiter\n"); return; } #if (NIMC > 0) imc_disable_sysad_parity(); #endif switch (sc->sc_gprid) { case PHOBOS_G100: case PHOBOS_G130: case PHOBOS_G160: pci_off = PHOBOS_PCI_OFFSET; pci_len = PHOBOS_PCI_LENGTH; m_start = MIPS_KSEG1_TO_PHYS(ga->ga_addr + PHOBOS_TULIP_START); m_end = MIPS_KSEG1_TO_PHYS(ga->ga_addr + PHOBOS_TULIP_END); break; case SETENG_GFE: /* * NB: The SetEng board does not allow the ThunderLAN's DMA * engine to properly transfer segments that span page * boundaries. See sgimips/autoconf.c where we catch a * tl(4) device attachment and create an appropriate * proplib entry to enable the workaround. */ pci_off = SETENG_PCI_OFFSET; pci_len = SETENG_PCI_LENGTH; m_start = MIPS_KSEG1_TO_PHYS(ga->ga_addr + SETENG_TLAN_START); m_end = MIPS_KSEG1_TO_PHYS(ga->ga_addr + SETENG_TLAN_END); bus_space_write_4(ga->ga_iot, ga->ga_ioh, SETENG_MAGIC_OFFSET, SETENG_MAGIC_VALUE); break; default: panic("giopci_attach: unsupported GIO product id 0x%02x", sc->sc_gprid); } if (bus_space_subregion(ga->ga_iot, ga->ga_ioh, pci_off, pci_len, &sc->sc_ioh)) { printf("%s: unable to map PCI registers\n",sc->sc_dev.dv_xname); return; } sc->sc_pci_len = pci_len; pc->pc_bus_maxdevs = giopci_bus_maxdevs; pc->pc_conf_read = giopci_conf_read; pc->pc_conf_write = giopci_conf_write; pc->pc_conf_hook = giopci_conf_hook; pc->pc_intr_map = giopci_intr_map; pc->pc_intr_string = giopci_intr_string; pc->intr_establish = giopci_intr_establish; pc->intr_disestablish = giopci_intr_disestablish; pc->iot = ga->ga_iot; pc->ioh = ga->ga_ioh; pc->cookie = sc; printf(": %s\n", gio_product_string(sc->sc_gprid)); #ifdef PCI_NETBSD_CONFIGURE pc->pc_memext = extent_create("giopcimem", m_start, m_end, M_DEVBUF, NULL, 0, EX_NOWAIT); pci_configure_bus(pc, NULL, pc->pc_memext, NULL, 0, mips_dcache_align); #endif memset(&pba, 0, sizeof(pba)); pba.pba_memt = SGIMIPS_BUS_SPACE_MEM; pba.pba_dmat = ga->ga_dmat; pba.pba_pc = pc; pba.pba_flags = PCI_FLAGS_MEM_ENABLED; /* NB: do not set PCI_FLAGS_{MRL,MRM,MWI}_OKAY -- true ?! */ config_found_ia(self, "pcibus", &pba, pcibusprint); }