static void uninorth_conf_write_v3(void *cookie, pcitag_t tag, int reg, pcireg_t data) { pci_chipset_tag_t pc = cookie; int32_t *daddr = pc->pc_data; int bus, dev, func, s; uint32_t x; if ((unsigned int)reg >= PCI_CONF_SIZE) return; /* UniNorth seems to have a 64bit data port */ if (reg & 0x04) daddr++; pci_decompose_tag(pc, tag, &bus, &dev, &func); x = (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 1; /* Set extended register bits */ x |= (reg >> 8) << 28; s = splhigh(); out32rb(pc->pc_addr, x); in32rb(pc->pc_addr); out32rb(daddr, data); out32rb(pc->pc_addr, 0); in32rb(pc->pc_addr); splx(s); }
/* * Reset and enable bmac by heathrow FCR. */ void bmac_reset_chip(struct bmac_softc *sc) { u_int v; dbdma_reset(sc->sc_txdma); dbdma_reset(sc->sc_rxdma); v = in32rb(heathrow_FCR); v |= EnetEnable; out32rb(heathrow_FCR, v); delay(50000); /* assert reset */ v |= ResetEnetCell; out32rb(heathrow_FCR, v); delay(50000); /* deassert reset */ v &= ~ResetEnetCell; out32rb(heathrow_FCR, v); delay(50000); /* enable */ v |= EnetEnable; out32rb(heathrow_FCR, v); delay(50000); /* make certain they stay set? */ out32rb(heathrow_FCR, v); v = in32rb(heathrow_FCR); }
static void grackle_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, u_int32_t val, int width) { struct grackle_softc *sc; vm_offset_t caoff; sc = device_get_softc(dev); caoff = sc->sc_data + (reg & 0x03); if (grackle_enable_config(sc, bus, slot, func, reg)) { switch (width) { case 1: out8rb(caoff, val); (void)in8rb(caoff); break; case 2: out16rb(caoff, val); (void)in16rb(caoff); break; case 4: out32rb(caoff, val); (void)in32rb(caoff); break; } } grackle_disable_config(sc); }
void macobio_modem_power(int enable) { u_int32_t val; struct macobio_softc *sc = macobio_cd.cd_devs[0]; if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_KEYLARGO || PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_INTREPID) { val = in32rb(sc->obiomem + 0x40); if (enable) val = val & ~((u_int32_t)1<<25); else val = val | ((u_int32_t)1<<25); out32rb(sc->obiomem + 0x40, val); } if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_PANGEA_MACIO) { if (enable) { /* set reset */ out8(sc->obiomem + 0x006a + 0x03, 0x04); /* power modem on */ out8(sc->obiomem + 0x006a + 0x02, 0x04); /* unset reset */ out8(sc->obiomem + 0x006a + 0x03, 0x05); } else { /* disable it how? */ } } }
pcireg_t prep_pci_direct_conf_read(void *v, pcitag_t tag, int reg) { pcireg_t data; int bus, device, function; int s; prep_pci_direct_decompose_tag(v, tag, &bus, &device, &function); if (bus == 0) { /* Check if device selector is within selector range. */ if (1 << device & ~PCI_DCONF_DEV) { data = ~0; goto out; } tag = (1 << device) | (function << PCI_DCONF_FUNC_SHIFT); } s = splhigh(); data = in32rb(PCI_DCONF_BASE | tag | reg); splx(s); out: return data; }
static status_t grackle_read_pci_config(void *cookie, uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 *value) { grackle_host_bridge *bridge = (grackle_host_bridge*)cookie; TRACE("grackle_read_pci_config(bus=%u, dev=%u, func=%u, offset=%u, " "size=%u)\n", (int)bus, (int)device, (int)function, (int)offset, (int)size); out32rb(bridge->address_registers, (1 << 31) | (bus << 16) | ((device & 0x1f) << 11) | ((function & 0x7) << 8) | (offset & 0xfc)); addr_t dataAddress = bridge->data_registers + (offset & 0x3); switch (size) { case 1: *value = in8rb(dataAddress); break; case 2: *value = in16rb(dataAddress); break; case 4: *value = in32rb(dataAddress); break; default: *value = 0xffffffff; break; } out32rb(bridge->address_registers, 0); return B_OK; }
static int uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot, u_int func, u_int reg) { u_int32_t cfgval; if (sc->sc_bus == bus) { /* * No slots less than 11 on the primary bus */ if (slot < 11) return (0); cfgval = (1 << slot) | (func << 8) | (reg & 0xfc); } else { cfgval = (bus << 16) | (slot << 11) | (func << 8) | (reg & 0xfc) | 1; } do { out32rb(sc->sc_addr, cfgval); } while (in32rb(sc->sc_addr) != cfgval); return (1); }
static u_int32_t uninorth_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) { struct uninorth_softc *sc; vm_offset_t caoff; sc = device_get_softc(dev); caoff = sc->sc_data + (reg & 0x07); if (uninorth_enable_config(sc, bus, slot, func, reg) != 0) { switch (width) { case 1: return (in8rb(caoff)); break; case 2: return (in16rb(caoff)); break; case 4: return (in32rb(caoff)); break; } } return (0xffffffff); }
void pchbattach(struct device *parent, struct device *self, void *aux) { struct pci_attach_args *pa = aux; char devinfo[256]; #if NAGP > 0 struct agpbus_attach_args apa; #endif volatile unsigned char *python; uint32_t v; aprint_normal("\n"); /* * All we do is print out a description. Eventually, we * might want to add code that does something that's * possibly chipset-specific. */ pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); aprint_normal("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo, PCI_REVISION(pa->pa_class)); switch (PCI_VENDOR(pa->pa_id)) { case PCI_VENDOR_IBM: switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_IBM_82660: ibm82660_print(pa, self); break; case PCI_PRODUCT_IBM_PYTHON: python = mapiodev(0xfeff6000, 0x60); v = 0x88b78e01; /* taken from linux */ out32rb(python+0x30, v); v = in32rb(python+0x30); aprint_debug("Reset python reg 30 to 0x%x\n", v); break; } break; case PCI_VENDOR_MOT: switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_MOT_MPC105: mpc105_print(pa, self); break; case PCI_PRODUCT_MOT_MPC106: mpc106_print(pa, self); break; } break; } #if NAGP > 0 if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL) != 0) { apa.apa_pci_args = *pa; config_found_ia(self, "agpbus", &apa, agpbusprint); } #endif /* NAGP */ }
static pcireg_t uninorth_conf_read(void *cookie, pcitag_t tag, int reg) { pci_chipset_tag_t pc = cookie; int32_t *daddr = pc->pc_data; pcireg_t data; int bus, dev, func, s; uint32_t x; if ((unsigned int)reg >= PCI_CONF_SIZE) return (pcireg_t) -1; /* UniNorth seems to have a 64bit data port */ if (reg & 0x04) daddr++; pci_decompose_tag(pc, tag, &bus, &dev, &func); /* * bandit's minimum device number of the first bus is 11. * So we behave as if there is no device when dev < 11. */ if (func > 7) panic("pci_conf_read: func > 7"); if (bus == pc->pc_bus) { if (dev < 11) return 0xffffffff; x = (1 << dev) | (func << 8) | reg; } else x = tag | reg | 1; s = splhigh(); out32rb(pc->pc_addr, x); in32rb(pc->pc_addr); data = 0xffffffff; if (!badaddr(daddr, 4)) data = in32rb(daddr); out32rb(pc->pc_addr, 0); in32rb(pc->pc_addr); splx(s); return data; }
u_int32_t keylargo_fcr_read(int offset) { struct macobio_softc *sc = macobio_cd.cd_devs[0]; if (sc->obiomem == 0) return -1; return in32rb(sc->obiomem + offset); }
/* enable an IRQ on the IOCC */ static void iocc_enable_irq(struct pic_ops *pic, int irq, int type) { uint32_t mask; mask = in32rb(RS6000_BUS_SPACE_IO + IOCC_IEE); mask |= 1 << irq; out32rb(RS6000_BUS_SPACE_IO + IOCC_IEE, mask); }
/* disable an IRQ on the IOCC */ static void iocc_disable_irq(struct pic_ops *pic, int irq) { uint32_t mask; mask = in32rb(RS6000_BUS_SPACE_IO + IOCC_IEE); mask &= ~(1 << irq); out32rb(RS6000_BUS_SPACE_IO + IOCC_IEE, mask); }
void macobio_disable(int offset, u_int32_t bits) { struct macobio_softc *sc = macobio_cd.cd_devs[0]; if (sc->obiomem == 0) return; bits = in32rb(sc->obiomem + offset) & ~bits; out32rb(sc->obiomem + offset, bits); }
void keylargo_fcr_enable(int offset, u_int32_t bits) { struct macobio_softc *sc = macobio_cd.cd_devs[0]; if (sc->obiomem == 0) return; bits |= in32rb(sc->obiomem + offset); out32rb(sc->obiomem + offset, bits); }
static void ibm82660_print(struct pci_attach_args *pa, struct device *self) { pcireg_t reg1; #ifdef PREP_BUS_SPACE_IO pcireg_t reg2; #endif const char *s1, *s2; reg1 = pci_conf_read(pa->pa_pc, pa->pa_tag, IBM_82660_CACHE_STATUS); #ifdef PREP_BUS_SPACE_IO reg2 = in32rb(PREP_BUS_SPACE_IO+IBM_82660_SYSTEM_CTRL); if (reg2 & IBM_82660_SYSTEM_CTRL_L2_EN) { if (reg1 & IBM_82660_CACHE_STATUS_L2_EN) s1 = "internal enabled"; else s1 = "enabled"; if (reg2 & IBM_82660_SYSTEM_CTRL_L2_MI) s2 = "(normal operation)"; else s2 = "(miss updates inhibited)"; } else { s1 = "disabled"; s2 = ""; } #else if (reg1 & IBM_82660_CACHE_STATUS_L2_EN) s1 = "enabled"; else s1 = "disabled"; s2 = ""; #endif aprint_normal("%s: L1: %s L2: %s %s\n", self->dv_xname, (reg1 & IBM_82660_CACHE_STATUS_L1_EN) ? "enabled" : "disabled", s1, s2); reg1 = pci_conf_read(pa->pa_pc, pa->pa_tag, IBM_82660_OPTIONS_1); aprint_verbose("%s: MCP# assertion %s " "TEA# assertion %s\n", self->dv_xname, (reg1 & IBM_82660_OPTIONS_1_MCP) ? "enabled" : "disabled", (reg1 & IBM_82660_OPTIONS_1_TEA) ? "enabled" : "disabled"); aprint_verbose("%s: PCI/ISA I/O mapping %s\n", self->dv_xname, (reg1 & IBM_82660_OPTIONS_1_ISA) ? "contiguous" : "non-contiguous"); reg1 = pci_conf_read(pa->pa_pc, pa->pa_tag, IBM_82660_OPTIONS_3); aprint_normal("%s: DRAM %s (%s) SRAM %s\n", self->dv_xname, (reg1 & IBM_82660_OPTIONS_3_DRAM) ? "EDO" : "standard", (reg1 & IBM_82660_OPTIONS_3_ECC) ? "ECC" : "parity", (reg1 & IBM_82660_OPTIONS_3_SRAM) ? "sync" : "async"); aprint_verbose("%s: Snoop mode %s\n", self->dv_xname, (reg1 & IBM_82660_OPTIONS_3_SNOOP) ? "603" : "601/604"); }
/* * The Kahlua documentation says that "reg" should be left-shifted by two * and be in bits 2-7. Apparently not. It doesn't work that way, and the * DINK32 ROM doesn't do it that way (I peeked at 0xfec00000 after running * the DINK32 "pcf" command). */ pcireg_t pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t data; if ((unsigned int)reg >= PCI_CONF_SIZE) return (pcireg_t) -1; out32rb(SANDPOINT_PCI_CONFIG_ADDR, tag | reg); data = in32rb(SANDPOINT_PCI_CONFIG_DATA); out32rb(SANDPOINT_PCI_CONFIG_ADDR, 0); return data; }
pcireg_t ibmnws_pci_indirect_conf_read(void *v, pcitag_t tag, int reg) { pcireg_t data; int s; s = splhigh(); out32rb(PCI_MODE1_ADDRESS_REG, tag | reg); data = in32rb(PCI_MODE1_DATA_REG); out32rb(PCI_MODE1_ADDRESS_REG, 0); splx(s); return data; }
static void uninorth_conf_write(void *cookie, pcitag_t tag, int reg, pcireg_t data) { pci_chipset_tag_t pc = cookie; int32_t *daddr = pc->pc_data; int bus, dev, func, s; uint32_t x; if ((unsigned int)reg >= PCI_CONF_SIZE) return; /* UniNorth seems to have a 64bit data port */ if (reg & 0x04) daddr++; pci_decompose_tag(pc, tag, &bus, &dev, &func); if (func > 7) panic("pci_conf_write: func > 7"); if (bus == pc->pc_bus) { if (dev < 11) panic("pci_conf_write: dev < 11"); x = (1 << dev) | (func << 8) | reg; } else x = tag | reg | 1; s = splhigh(); out32rb(pc->pc_addr, x); in32rb(pc->pc_addr); out32rb(daddr, data); out32rb(pc->pc_addr, 0); in32rb(pc->pc_addr); splx(s); }
/* * the IOCC IER is a bitmask of pending IRQs, where only 0-15 are valid */ static int iocc_get_irq(struct pic_ops *pic, int mode) { int irq; uint32_t rv = 0; rv = in32rb(RS6000_BUS_SPACE_IO + IOCC_IRR); if (rv == 0) return 255; irq = 31 - __builtin_clz(rv); if (irq >= 0 && irq < 16) return irq; return 255; }
static int grackle_enable_config(struct grackle_softc *sc, u_int bus, u_int slot, u_int func, u_int reg) { u_int32_t cfgval; /* * Unlike UniNorth, the format of the config word is the same * for local (0) and remote busses. */ cfgval = (bus << 16) | (slot << 11) | (func << 8) | (reg & 0xFC) | GRACKLE_CFG_ENABLE; out32rb(sc->sc_addr, cfgval); (void) in32rb(sc->sc_addr); return (1); }
static pcireg_t grackle_conf_read(void *cookie, pcitag_t tag, int reg) { pci_chipset_tag_t pc = cookie; pcireg_t data; int s; s = splhigh(); out32rb(pc->pc_addr, tag | reg); data = 0xffffffff; if (!badaddr(pc->pc_data, 4)) data = in32rb(pc->pc_data); out32rb(pc->pc_addr, 0); splx(s); return data; }
static int uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot, u_int func, u_int reg) { uint32_t cfgval; uint32_t pass; if (resource_int_value(device_get_name(sc->pci_sc.sc_dev), device_get_unit(sc->pci_sc.sc_dev), "skipslot", &pass) == 0) { if (pass == slot) return (0); } /* * Issue type 0 configuration space accesses for the root bus. * * NOTE: On U4, issue only type 1 accesses. There is a secret * PCI Express <-> PCI Express bridge not present in the device tree, * and we need to route all of our configuration space through it. */ if (sc->pci_sc.sc_bus == bus && sc->sc_ver < 4) { /* * No slots less than 11 on the primary bus on U3 and lower */ if (slot < 11) return (0); cfgval = (1 << slot) | (func << 8) | (reg & 0xfc); } else { cfgval = (bus << 16) | (slot << 11) | (func << 8) | (reg & 0xfc) | 1; } /* Set extended register bits on U4 */ if (sc->sc_ver == 4) cfgval |= (reg >> 8) << 28; do { out32rb(sc->sc_addr, cfgval); } while (in32rb(sc->sc_addr) != cfgval); return (1); }
static u_int32_t grackle_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) { struct grackle_softc *sc; vm_offset_t caoff; u_int32_t retval = 0xffffffff; sc = device_get_softc(dev); caoff = sc->sc_data + (reg & 0x03); if (grackle_enable_config(sc, bus, slot, func, reg) != 0) { /* * Config probes to non-existent devices on the * secondary bus generates machine checks. Be sure * to catch these. */ if (bus > 0) { if (badaddr((void *)sc->sc_data, 4)) { return (retval); } } switch (width) { case 1: retval = (in8rb(caoff)); break; case 2: retval = (in16rb(caoff)); break; case 4: retval = (in32rb(caoff)); break; } } grackle_disable_config(sc); return (retval); }
static void battery_attach(struct device *parent, struct device *self, void *aux) { struct battery_attach_args *baa = aux; struct battery_softc *sc = (struct battery_softc *)self; uint32_t reg; sc->sc_pmu_ops = baa->baa_pmu_ops; printf(": legacy battery "); reg = in32rb(0xf3000034); DPRINTF("reg: %08x\n", reg); if (reg & 0x20000000) { sc->sc_type = BTYPE_HOOPER; sc->sc_vmax_charged = 330; sc->sc_vmax_charging = 365; printf("[hooper]\n"); } else { sc->sc_type = BTYPE_COMET; sc->sc_vmax_charged = 189; sc->sc_vmax_charging = 213; printf("[comet]\n"); } battery_update(sc, 1); /* trigger a status update */ sc->sc_oflags = ~sc->sc_flags; battery_setup_envsys(sc); sc->sc_pmu_ops->register_callback(sc->sc_pmu_ops->cookie, battery_poll, sc); memset(&sc->sc_sm_acpower, 0, sizeof(struct sysmon_pswitch)); sc->sc_sm_acpower.smpsw_name = "AC Power"; sc->sc_sm_acpower.smpsw_type = PSWITCH_TYPE_ACADAPTER; if (sysmon_pswitch_register(&sc->sc_sm_acpower) != 0) printf("%s: unable to register AC power status with sysmon\n", sc->sc_dev.dv_xname); }
void xlights_attach(struct device *parent, struct device *self, void *aux) { struct xlights_softc *sc = (struct xlights_softc *)self; struct confargs *ca = aux; int nseg, error, intr[6]; u_int32_t reg[4]; int type; sc->sc_node = OF_child(ca->ca_node); OF_getprop(sc->sc_node, "reg", reg, sizeof(reg)); ca->ca_reg[0] += ca->ca_baseaddr; ca->ca_reg[2] += ca->ca_baseaddr; if ((sc->sc_reg = mapiodev(ca->ca_reg[0], ca->ca_reg[1])) == NULL) { printf(": cannot map registers\n"); return; } sc->sc_dmat = ca->ca_dmat; if ((sc->sc_dma = mapiodev(ca->ca_reg[2], ca->ca_reg[3])) == NULL) { printf(": cannot map DMA registers\n"); goto nodma; } if ((sc->sc_dbdma = dbdma_alloc(sc->sc_dmat, BL_DBDMA_CMDS)) == NULL) { printf(": cannot alloc DMA descriptors\n"); goto nodbdma; } sc->sc_dmacmd = sc->sc_dbdma->d_addr; if ((error = bus_dmamem_alloc(sc->sc_dmat, BL_BUFSZ, 0, 0, sc->sc_bufseg, 1, &nseg, BUS_DMA_NOWAIT))) { printf(": cannot allocate DMA mem (%d)\n", error); goto nodmamem; } if ((error = bus_dmamem_map(sc->sc_dmat, sc->sc_bufseg, nseg, BL_BUFSZ, (caddr_t *)&sc->sc_buf, BUS_DMA_NOWAIT))) { printf(": cannot map DMA mem (%d)\n", error); goto nodmamap; } sc->sc_bufpos = sc->sc_buf; if ((error = bus_dmamap_create(sc->sc_dmat, BL_BUFSZ, 1, BL_BUFSZ, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_bufmap))) { printf(": cannot create DMA map (%d)\n", error); goto nodmacreate; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_bufmap, sc->sc_buf, BL_BUFSZ, NULL, BUS_DMA_NOWAIT))) { printf(": cannot load DMA map (%d)\n", error); goto nodmaload; } /* XXX: Should probably extract this from the clock data * property of the soundchip node */ sc->sc_freq = 16384; OF_getprop(sc->sc_node, "interrupts", intr, sizeof(intr)); /* output interrupt */ sc->sc_intr = intr[2]; type = intr[3] ? IST_LEVEL : IST_EDGE; printf(": irq %d\n", sc->sc_intr); macobio_enable(I2SClockOffset, I2S0EN); out32rb(sc->sc_reg + I2S_INT, I2S_INT_CLKSTOPPEND); macobio_disable(I2SClockOffset, I2S0CLKEN); for (error = 0; error < 1000; error++) { if (in32rb(sc->sc_reg + I2S_INT) & I2S_INT_CLKSTOPPEND) { error = 0; break; } delay(1); } if (error) { printf("%s: i2s timeout\n", sc->sc_dev.dv_xname); goto nodmaload; } mac_intr_establish(parent, sc->sc_intr, intr[3] ? IST_LEVEL : type, IPL_AUDIO, xlights_intr, sc, sc->sc_dev.dv_xname); out32rb(sc->sc_reg + I2S_FORMAT, CLKSRC_VS); macobio_enable(I2SClockOffset, I2S0CLKEN); kthread_create_deferred(xlights_deferred, sc); timeout_set(&sc->sc_tmo, xlights_timeout, sc); return; nodmaload: bus_dmamap_destroy(sc->sc_dmat, sc->sc_bufmap); nodmacreate: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_buf, BL_BUFSZ); nodmamap: bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, nseg); nodmamem: dbdma_free(sc->sc_dbdma); nodbdma: unmapiodev((void *)sc->sc_dma, ca->ca_reg[3]); nodma: unmapiodev(sc->sc_reg, ca->ca_reg[1]); }
void wdc_obio_attach(device_t parent, device_t self, void *aux) { struct wdc_obio_softc *sc = device_private(self); struct wdc_regs *wdr; struct confargs *ca = aux; struct ata_channel *chp = &sc->sc_channel; int intr, i, type = IST_EDGE; int use_dma = 0; char path[80]; sc->sc_wdcdev.sc_atac.atac_dev = self; if (device_cfdata(sc->sc_wdcdev.sc_atac.atac_dev)->cf_flags & WDC_OPTIONS_DMA) { if (ca->ca_nreg >= 16 || ca->ca_nintr == -1) use_dma = 1; /* XXX Don't work yet. */ } if (ca->ca_nintr >= 4 && ca->ca_nreg >= 8) { intr = ca->ca_intr[0]; aprint_normal(" irq %d", intr); if (ca->ca_nintr > 8) { type = ca->ca_intr[1] ? IST_LEVEL : IST_EDGE; } aprint_normal(", %s triggered", (type == IST_EDGE) ? "edge" : "level"); } else if (ca->ca_nintr == -1) { intr = WDC_DEFAULT_PIO_IRQ; aprint_normal(" irq property not found; using %d", intr); } else { aprint_error(": couldn't get irq property\n"); return; } if (use_dma) aprint_normal(": DMA transfer"); aprint_normal("\n"); sc->sc_wdcdev.regs = wdr = &sc->sc_wdc_regs; wdr->cmd_iot = wdr->ctl_iot = ca->ca_tag; if (bus_space_map(wdr->cmd_iot, ca->ca_baseaddr + ca->ca_reg[0], WDC_REG_NPORTS << 4, 0, &wdr->cmd_baseioh) || bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, WDC_AUXREG_OFFSET << 4, 1, &wdr->ctl_ioh)) { aprint_error_dev(self, "couldn't map registers\n"); return; } for (i = 0; i < WDC_NREG; i++) { if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, i << 4, i == 0 ? 4 : 1, &wdr->cmd_iohs[i]) != 0) { bus_space_unmap(wdr->cmd_iot, wdr->cmd_baseioh, WDC_REG_NPORTS << 4); aprint_error_dev(self, "couldn't subregion registers\n"); return; } } #if 0 wdr->data32iot = wdr->cmd_iot; wdr->data32ioh = wdr->cmd_ioh; #endif sc->sc_ih = intr_establish(intr, type, IPL_BIO, wdcintr, chp); if (use_dma) { sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20); /* * XXX * we don't use ca->ca_reg[3] for size here because at least * on the PB3400c it says 0x200 for both IDE channels ( the * one on the mainboard and the other on the mediabay ) but * their start addresses are only 0x100 apart. Since those * DMA registers are always 0x100 or less we don't really * have to care though */ if (bus_space_map(wdr->cmd_iot, ca->ca_baseaddr + ca->ca_reg[2], 0x100, BUS_SPACE_MAP_LINEAR, &sc->sc_dmaregh)) { aprint_error_dev(self, "unable to map DMA registers (%08x)\n", ca->ca_reg[2]); /* should unmap stuff here */ return; } sc->sc_dmareg = bus_space_vaddr(wdr->cmd_iot, sc->sc_dmaregh); sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA; sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; if (strcmp(ca->ca_name, "ata-4") == 0) { sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA; sc->sc_wdcdev.sc_atac.atac_udma_cap = 4; sc->sc_wdcdev.sc_atac.atac_set_modes = ata4_adjust_timing; } else { sc->sc_wdcdev.sc_atac.atac_set_modes = adjust_timing; } #ifdef notyet /* Minimum cycle time is 150ns (DMA MODE 1) on ohare. */ if (ohare) { sc->sc_wdcdev.sc_atac.atac_pio_cap = 3; sc->sc_wdcdev.sc_atac.atac_dma_cap = 1; } #endif } else { /* all non-DMA controllers can use adjust_timing */ sc->sc_wdcdev.sc_atac.atac_set_modes = adjust_timing; } sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16; sc->sc_chanptr = chp; sc->sc_wdcdev.sc_atac.atac_channels = &sc->sc_chanptr; sc->sc_wdcdev.sc_atac.atac_nchannels = 1; sc->sc_wdcdev.wdc_maxdrives = 2; sc->sc_wdcdev.dma_arg = sc; sc->sc_wdcdev.dma_init = wdc_obio_dma_init; sc->sc_wdcdev.dma_start = wdc_obio_dma_start; sc->sc_wdcdev.dma_finish = wdc_obio_dma_finish; chp->ch_channel = 0; chp->ch_atac = &sc->sc_wdcdev.sc_atac; chp->ch_queue = &sc->sc_chqueue; wdc_init_shadow_regs(chp); #define OHARE_FEATURE_REG 0xf3000038 /* XXX Enable wdc1 by feature reg. */ memset(path, 0, sizeof(path)); OF_package_to_path(ca->ca_node, path, sizeof(path)); if (strcmp(path, "/bandit@F2000000/ohare@10/ata@21000") == 0) { u_int x; x = in32rb(OHARE_FEATURE_REG); x |= 8; out32rb(OHARE_FEATURE_REG, x); } wdcattach(chp); }
static void mbattach(struct device *parent, struct device *self, void *aux) { struct mainbus_softc *sc = (struct mainbus_softc *)self; struct confargs nca; char name[64], *t = NULL; int reg[4], cpucnt; int node, len, slen; node = OF_peer(0); len = OF_getprop(node, "model", name, sizeof(name)); if (len > 1) { name[len] = '\0'; slen = strlen(name)+1; if ((t = malloc(slen, M_DEVBUF, M_NOWAIT)) != NULL) strlcpy(t, name, slen); } len = OF_getprop(node, "compatible", name, sizeof(name)); if (len > 1) { name[len] = '\0'; /* Old World Macintosh */ if ((strncmp(name, "AAPL", 4)) == 0) { hw_vendor = "Apple Computer, Inc."; slen = strlen(t) + strlen(name) - 3; if ((hw_prod = malloc(slen, M_DEVBUF, M_NOWAIT)) != NULL) { snprintf(hw_prod, slen, "%s %s", t, name + 5); free(t, M_DEVBUF); } } else { /* New World Macintosh or Unknown */ hw_vendor = "Apple Computer, Inc."; hw_prod = t; } } printf(": model %s\n", hw_prod); sc->sc_bus.bh_dv = (struct device *)sc; sc->sc_bus.bh_type = BUS_MAIN; sc->sc_bus.bh_intr_establish = mb_intr_establish; sc->sc_bus.bh_intr_disestablish = mb_intr_disestablish; sc->sc_bus.bh_matchname = mb_matchname; /* * Try to find and attach all of the CPUs in the machine. */ cpucnt = 0; node = OF_finddevice("/cpus"); if (node != -1) { for (node = OF_child(node); node != 0; node = OF_peer(node)) { u_int32_t cpunum; int len; len = OF_getprop(node, "reg", &cpunum, sizeof cpunum); if (len == 4 && cpucnt == cpunum) { nca.ca_name = "cpu"; nca.ca_bus = &sc->sc_bus; nca.ca_reg = reg; reg[0] = cpucnt; config_found(self, &nca, mbprint); cpucnt++; } } } if (cpucnt == 0) { nca.ca_name = "cpu"; nca.ca_bus = &sc->sc_bus; nca.ca_reg = reg; reg[0] = 0; config_found(self, &nca, mbprint); } /* * Special hack for SMP old world macs which lack /cpus and only have * one cpu node. */ node = OF_finddevice("/hammerhead"); if (node != -1) { len = OF_getprop(node, "reg", reg, sizeof(reg)); if (len >= 2) { u_char *hh_base; int twoway = 0; if ((hh_base = mapiodev(reg[0], reg[1])) != NULL) { twoway = in32rb(hh_base + HH_REG_CONF) & 0x02; unmapiodev(hh_base, reg[1]); } if (twoway) { nca.ca_name = "cpu"; nca.ca_bus = &sc->sc_bus; nca.ca_reg = reg; reg[0] = 1; config_found(self, &nca, mbprint); } } } for (node = OF_child(OF_peer(0)); node; node=OF_peer(node)) { bzero (name, sizeof(name)); if (OF_getprop(node, "device_type", name, sizeof(name)) <= 0) { if (OF_getprop(node, "name", name, sizeof(name)) <= 0) printf ("name not found on node %x\n", node); continue; } if (strcmp(name, "memory") == 0) { nca.ca_name = "mem"; nca.ca_node = node; nca.ca_bus = &sc->sc_bus; config_found(self, &nca, mbprint); } if (strcmp(name, "memory-controller") == 0) { nca.ca_name = "memc"; nca.ca_node = node; nca.ca_bus = &sc->sc_bus; config_found(self, &nca, mbprint); } if (strcmp(name, "pci") == 0) { nca.ca_name = "mpcpcibr"; nca.ca_node = node; nca.ca_bus = &sc->sc_bus; config_found(self, &nca, mbprint); } if (strcmp(name, "ht") == 0) { nca.ca_name = "ht"; nca.ca_node = node; nca.ca_bus = &sc->sc_bus; config_found(self, &nca, mbprint); } if (strcmp(name, "smu") == 0) { nca.ca_name = "smu"; nca.ca_node = node; nca.ca_bus = &sc->sc_bus; config_found(self, &nca, mbprint); } } }