void gemattach_sbus(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa = aux; struct gem_sbus_softc *gsc = (void *)self; struct gem_softc *sc = &gsc->gsc_gem; /* XXX the following declarations should be elsewhere */ extern void myetheraddr(u_char *); /* Pass on the bus tags */ sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; if (sa->sa_nreg < 2) { printf("%s: only %d register sets\n", self->dv_xname, sa->sa_nreg); return; } /* * Map two register banks: * * bank 0: status, config, reset * bank 1: various gem parts * */ if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, (bus_addr_t)sa->sa_reg[0].sbr_offset, (bus_size_t)sa->sa_reg[0].sbr_size, 0, 0, &sc->sc_h2) != 0) { printf("%s: cannot map registers\n", self->dv_xname); return; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, (bus_addr_t)sa->sa_reg[1].sbr_offset, (bus_size_t)sa->sa_reg[1].sbr_size, 0, 0, &sc->sc_h1) != 0) { printf("%s: cannot map registers\n", self->dv_xname); return; } if (OF_getprop(sa->sa_node, "local-mac-address", sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0) myetheraddr(sc->sc_arpcom.ac_enaddr); /* * SBUS config */ bus_space_write_4(sa->sa_bustag, sc->sc_h2, GEM_SBUS_CONFIG, GEM_SBUS_CFG_PARITY|GEM_SBUS_CFG_BMODE64); /* Establish interrupt handler */ if (sa->sa_nintr != 0) (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, 0, gem_intr, sc, self->dv_xname); gem_config(sc); }
void apio_attach(struct device *parent, struct device *self, void *aux) { struct apio_softc *sc = (void *)self; struct sbus_attach_args *sa = aux; struct apio_attach_args aaa; char *model; sc->sc_bt = sa->sa_bustag; model = getpropstring(sa->sa_node, "model"); if (model == NULL) { printf(": empty model, unsupported\n"); return; } if (strcmp(model, "210sj") != 0) { printf(": unsupported model %s\n", model); return; } if (sa->sa_nreg < 3) { printf(": %d registers expected, got %d\n", 3, sa->sa_nreg); return; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 0, 0, &sc->sc_csr_h)) { printf(": couldn't map csr\n"); return; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot, sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size, 0, 0, &sc->sc_clk_h)) { printf(": couldn't map clk\n"); return; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[2].sbr_slot, sa->sa_reg[2].sbr_offset, sa->sa_reg[2].sbr_size, 0, 0, &sc->sc_lpt_h)) { printf(": couldn't map clk\n"); return; } printf(": %s\n", model); aaa.aaa_name = "lpt"; aaa.aaa_iot = sc->sc_bt; aaa.aaa_ioh = sc->sc_lpt_h; aaa.aaa_clkh = sc->sc_clk_h; aaa.aaa_inten = ASIO_CSR_SJ_PAR_INTEN; aaa.aaa_pri = sa->sa_intr[0].sbi_pri; sc->sc_port = config_found(self, &aaa, apio_print); }
void ti_sbus_attach(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa = aux; struct ti_sbus_softc *tsc = (void *)self; struct ti_softc *sc = &tsc->tsc_sc; bus_space_handle_t ioh; /* Pass on the bus tags */ sc->ti_btag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; if (sa->sa_nintr < 1) { printf(": no interrupt\n"); return; } if (sa->sa_nreg < 2) { printf(": only %d register sets\n", sa->sa_nreg); return; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot, sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size, 0, 0, &sc->ti_bhandle)) { printf(": can't map registers\n"); return; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 0, 0, &ioh)) { printf(": can't map registers\n"); goto unmap; } bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, 0, ti_intr, sc, self->dv_xname); bus_space_write_4(sa->sa_bustag, ioh, TI_PCI_CMDSTAT, 0x02000006); bus_space_write_4(sa->sa_bustag, ioh, TI_PCI_BIST, 0xffffffff); bus_space_write_4(sa->sa_bustag, ioh, TI_PCI_LOMEM, 0x00000400); bus_space_unmap(sa->sa_bustag, ioh, sa->sa_reg[0].sbr_size); sc->ti_sbus = 1; if (ti_attach(sc) == 0) return; unmap: bus_space_unmap(sa->sa_bustag, sc->ti_bhandle, sa->sa_reg[1].sbr_size); }
/* ARGSUSED */ static void memregattach_obio(device_t parent, device_t self, void *aux) { union obio_attach_args *uoba = aux; bus_space_handle_t bh; if (uoba->uoba_isobio4 == 0) { struct sbus_attach_args *sa = &uoba->uoba_sbus; if (sa->sa_promvaddr != 0) { par_err_reg = (volatile int *)sa->sa_promvaddr; return; } if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sizeof(par_err_reg), BUS_SPACE_MAP_LINEAR, &bh) != 0) { printf("memregattach_obio: can't map register\n"); return; } par_err_reg = (volatile int *)bh; } /* On sun4, `par_err_reg' has already been mapped in autoconf.c */ if (par_err_reg == NULL) panic("memregattach"); printf("\n"); }
static int com_obio_match(device_t parent, cfdata_t cf, void *aux) { union obio_attach_args *uoba = aux; struct sbus_attach_args *sa = &uoba->uoba_sbus; int tadpole = 0; int need_probe = 0; int rv = 0; uint8_t auxregval = 0; if (uoba->uoba_isobio4 != 0) { return (0); } /* * Tadpole 3GX/3GS uses "modem" for a 16450 port * (We need to enable it before probing) */ if (strcmp("modem", sa->sa_name) == 0) { auxregval = *AUXIO4M_REG; *AUXIO4M_REG = auxregval | (AUXIO4M_LED|AUXIO4M_LTE); DELAY(100); tadpole = 1; need_probe = 1; } /* * Sun JavaStation 1 uses "su" for a 16550 port */ if (strcmp("su", sa->sa_name) == 0) { need_probe = 1; } if (need_probe) { bus_space_handle_t ioh; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, BUS_SPACE_MAP_LINEAR, &ioh) == 0) { rv = comprobe1(sa->sa_bustag, ioh); #if 0 printf("modem: probe: lcr=0x%02x iir=0x%02x\n", bus_space_read_1(sa->sa_bustag, ioh, 3), bus_space_read_1(sa->sa_bustag, ioh, 2)); #endif bus_space_unmap(sa->sa_bustag, ioh, sa->sa_size); } } /* Disable the com port if tadpole */ if (tadpole) *AUXIO4M_REG = auxregval; return (rv); }
int rfx_initialize(struct rfx_softc *sc, struct sbus_attach_args *sa, struct rfx_config *cf) { u_int32_t *data, offset, value; size_t cnt; bus_space_handle_t bh; int error; /* * Map the initialization data */ if ((error = sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset + RFX_INIT_ADDR, RFX_INIT_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh)) != 0) { printf("\n%s: couldn't map initialization data\n", sc->sc_sunfb.sf_dev.dv_xname); return error; } data = (u_int32_t *)bus_space_vaddr(sa->sa_bustag, bh); /* * Skip copyright notice */ data += RFX_INIT_OFFSET / sizeof(u_int32_t); cnt = (RFX_INIT_SIZE - RFX_INIT_OFFSET) / sizeof(u_int32_t); cnt >>= 1; /* * Parse and apply settings */ while (cnt != 0) { offset = *data++; value = *data++; if (offset == (u_int32_t)-1 && value == (u_int32_t)-1) break; /* Old PROM are little-endian */ if (cf->version <= 1) { offset = letoh32(offset); value = letoh32(offset); } if (offset & (1 << 31)) { offset = (offset & ~(1 << 31)) - RFX_RAMDAC_ADDR; if (offset < RFX_RAMDAC_SIZE) sc->sc_ramdac[offset] = value >> 24; } else {
void leattach_lebuffer(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa = aux; struct le_softc *lesc = (struct le_softc *)self; struct am7990_softc *sc = &lesc->sc_am7990; struct lebuf_softc *lebuf = (struct lebuf_softc *)parent; /* XXX the following declarations should be elsewhere */ extern void myetheraddr(u_char *); lesc->sc_bustag = sa->sa_bustag; lesc->sc_dmatag = sa->sa_dmatag; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, 0, &lesc->sc_reg)) { printf(": cannot map registers\n"); return; } sc->sc_mem = lebuf->sc_buffer; sc->sc_memsize = lebuf->sc_bufsiz; sc->sc_addr = 0; /* Lance view is offset by buffer location */ lebuf->attached = 1; /* That old black magic... */ sc->sc_conf3 = getpropint(sa->sa_node, "busmaster-regval", LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON); myetheraddr(sc->sc_arpcom.ac_enaddr); sc->sc_copytodesc = am7990_copytobuf_contig; sc->sc_copyfromdesc = am7990_copyfrombuf_contig; sc->sc_copytobuf = am7990_copytobuf_contig; sc->sc_copyfrombuf = am7990_copyfrombuf_contig; sc->sc_zerobuf = am7990_zerobuf_contig; sc->sc_rdcsr = le_lebuffer_rdcsr; sc->sc_wrcsr = le_lebuffer_wrcsr; am7990_config(&lesc->sc_am7990); /* Establish interrupt handler */ if (sa->sa_nintr != 0) (void)bus_intr_establish(lesc->sc_bustag, sa->sa_pri, IPL_NET, 0, am7990_intr, sc, self->dv_xname); }
/* ARGSUSED */ static void powerattach(device_t parent, device_t self, void *aux) { union obio_attach_args *uoba = aux; struct sbus_attach_args *sa = &uoba->uoba_sbus; bus_space_handle_t bh; /* Map the power configuration register. */ if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sizeof(uint8_t), BUS_SPACE_MAP_LINEAR, &bh) != 0) { printf("%s: cannot map register\n", device_xname(self)); return; } power_reg = (volatile uint8_t *)bh; printf("\n"); }
void uperf_sbus_attach(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa = aux; struct uperf_sbus_softc *sc = (struct uperf_sbus_softc *)self; char *model; u_int32_t id; sc->sc_bus_t = sa->sa_bustag; sc->sc_usc.usc_cookie = sc; sc->sc_usc.usc_getcntsrc = uperf_sbus_getcntsrc; sc->sc_usc.usc_setcntsrc = uperf_sbus_setcntsrc; sc->sc_usc.usc_clrcnt = uperf_sbus_clrcnt; sc->sc_usc.usc_getcnt = uperf_sbus_getcnt; sc->sc_usc.usc_srcs = uperf_sbus_srcs; if (sa->sa_nreg != 1) { printf(": expected 1 register, got %d\n", sa->sa_nreg); return; } if (sbus_bus_map(sc->sc_bus_t, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 0, 0, &sc->sc_bus_h) != 0) { printf(": couldn't map registers\n"); return; } id = uperf_sbus_read_reg(sc, USC_ID); model = getpropstring(sa->sa_node, "model"); if (model == NULL || strlen(model) == 0) model = "unknown"; printf(": model %s (%x/%x) ports %d\n", model, (id & USC_ID_IMPL_M) >> USC_ID_IMPL_S, (id & USC_ID_VERS_M) >> USC_ID_VERS_S, (id & USC_ID_UPANUM_M) >> USC_ID_UPANUM_S); #ifdef DDB db_register_xir(uperf_sbus_xir, sc); #endif }
void audioamd_sbus_attach(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa; struct audioamd_softc *sc; bus_space_handle_t bh; sa = aux; sc = (struct audioamd_softc *)self; sc->sc_bt = sa->sa_bustag; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, AM7930_DREG_SIZE, 0, &bh) != 0) { printf("%s: cannot map registers\n", self->dv_xname); return; } sc->sc_bh = bh; audioamd_attach(sc, sa->sa_pri); }
void magma_attach(struct device *parent, struct device *dev, void *aux) { struct sbus_attach_args *sa = aux; struct magma_softc *sc = (struct magma_softc *)dev; const struct magma_board_info *card; char magma_prom[40], *clockstr; int chip, cd_clock; getpropstringA(sa->sa_node, "magma_prom", magma_prom); for (card = supported_cards; card->mb_name != NULL; card++) { if (strcmp(sa->sa_name, card->mb_sbusname) != 0) continue; if (strcmp(magma_prom, card->mb_name) == 0) break; } if (card->mb_name == NULL) { printf(": %s (unsupported)\n", magma_prom); return; } sc->sc_bustag = sa->sa_bustag; clockstr = getpropstring(sa->sa_node, "clock"); if (strlen(clockstr) == 0) cd_clock = 25; else { cd_clock = 0; while (*clockstr != '\0') cd_clock = cd_clock * 10 + *clockstr++ - '0'; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 0, 0, &sc->sc_iohandle) != 0) { printf(": can't map registers\n"); return; } if (sa->sa_nintr < 1) { printf(": can't find interrupt\n"); return; } sc->sc_ih = bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0, magma_hard, sc, dev->dv_xname); if (sc->sc_ih == NULL) { printf(": couldn't establish interrupt, pri %d\n", INTLEV(sa->sa_pri)); bus_space_unmap(sc->sc_bustag, sc->sc_iohandle, sa->sa_reg[0].sbr_size); return; } sc->sc_sih = softintr_establish(IPL_TTY, magma_soft, sc); if (sc->sc_sih == NULL) { printf(": can't get soft intr\n"); bus_space_unmap(sc->sc_bustag, sc->sc_iohandle, sa->sa_reg[0].sbr_size); return; } printf(": %s\n", card->mb_realname); sc->ms_board = card; sc->ms_ncd1400 = card->mb_ncd1400; sc->ms_ncd1190 = card->mb_ncd1190; /* the SVCACK* lines are daisychained */ if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, card->mb_svcackr, 1, &sc->sc_svcackrh)) { printf(": failed to map svcackr\n"); return; } if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, card->mb_svcackt, 1, &sc->sc_svcackth)) { printf(": failed to map svcackt\n"); return; } if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, card->mb_svcackm, 1, &sc->sc_svcackmh)) { printf(": failed to map svcackm\n"); return; } /* init the cd1400 chips */ for (chip = 0 ; chip < card->mb_ncd1400 ; chip++) { struct cd1400 *cd = &sc->ms_cd1400[chip]; cd->cd_clock = cd_clock; if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, card->mb_cd1400[chip], CD1400_REGMAPSIZE, &cd->cd_regh)) { printf(": failed to map cd1400 regs\n"); return; } cd->cd_regt = sc->sc_bustag; /* getpropstring(sa->sa_node, "chiprev"); */ /* seemingly the Magma drivers just ignore the propstring */ cd->cd_chiprev = CD1400_READ_REG(cd, CD1400_GFRCR); dprintf(("%s attach CD1400 %d addr 0x%x rev %x clock %dMHz\n", sc->ms_dev.dv_xname, chip, cd->cd_reg, cd->cd_chiprev, cd->cd_clock)); /* clear GFRCR */ CD1400_WRITE_REG(cd, CD1400_GFRCR, 0x00); /* reset whole chip */ cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); /* wait for revision code to be restored */ while (CD1400_READ_REG(cd, CD1400_GFRCR) != cd->cd_chiprev) ; /* set the Prescaler Period Register to tick at 1ms */ CD1400_WRITE_REG(cd, CD1400_PPR, ((cd->cd_clock * 1000000 / CD1400_PPR_PRESCALER + 500) / 1000)); /* * The LC2+1Sp card is the only card that doesn't have a * CD1190 for the parallel port, but uses channel 0 of the * CD1400, so we make a note of it for later and set up the * CD1400 for parallel mode operation. */ if (card->mb_npar && card->mb_ncd1190 == 0) { CD1400_WRITE_REG(cd, CD1400_GCR, CD1400_GCR_PARALLEL); cd->cd_parmode = 1; } } /* init the cd1190 chips */ for (chip = 0 ; chip < card->mb_ncd1190 ; chip++) { struct cd1190 *cd = &sc->ms_cd1190[chip]; if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle, card->mb_cd1190[chip], CD1190_REGMAPSIZE, &cd->cd_regh)) { printf(": failed to map cd1190 regs\n"); return; } cd->cd_regt = sc->sc_bustag; dprintf(("%s attach CD1190 %d addr 0x%x (failed)\n", sc->ms_dev.dv_xname, chip, cd->cd_reg)); /* XXX don't know anything about these chips yet */ } /* configure the children */ (void)config_found(dev, mtty_match, NULL); (void)config_found(dev, mbpp_match, NULL); }
void bppattach(device_t parent, device_t self, void *aux) { struct bpp_softc *dsc = device_private(self); struct lsi64854_softc *sc = &dsc->sc_lsi64854; struct sbus_softc *sbsc = device_private(parent); struct sbus_attach_args *sa = aux; int burst, sbusburst; int node; sc->sc_dev = self; selinit(&dsc->sc_rsel); selinit(&dsc->sc_wsel); dsc->sc_sih = softint_establish(SOFTINT_CLOCK, bppsoftintr, dsc); sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; node = sa->sa_node; /* Map device registers */ if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &sc->sc_regs) != 0) { aprint_error(": cannot map registers\n"); return; } /* * Get transfer burst size from PROM and plug it into the * controller registers. This is needed on the Sun4m; do * others need it too? */ sbusburst = sbsc->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ burst = prom_getpropint(node, "burst-sizes", -1); if (burst == -1) /* take SBus burst sizes */ burst = sbusburst; /* Clamp at parent's burst sizes */ burst &= sbusburst; sc->sc_burst = (burst & SBUS_BURST_32) ? 32 : (burst & SBUS_BURST_16) ? 16 : 0; /* Join the Sbus device family */ dsc->sc_sd.sd_reset = NULL; sbus_establish(&dsc->sc_sd, self); /* Initialize the DMA channel */ sc->sc_channel = L64854_CHANNEL_PP; lsi64854_attach(sc); /* Establish interrupt handler */ if (sa->sa_nintr) { sc->sc_intrchain = bppintr; sc->sc_intrchainarg = dsc; (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, bppintr, sc); } /* Allocate buffer XXX - should actually use dmamap_uio() */ dsc->sc_bufsz = 1024; dsc->sc_buf = malloc(dsc->sc_bufsz, M_DEVBUF, M_NOWAIT); /* XXX read default state */ { bus_space_handle_t h = sc->sc_regs; struct hwstate *hw = &dsc->sc_hwdefault; int ack_rate = sa->sa_frequency / 1000000; hw->hw_hcr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_HCR); hw->hw_ocr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_OCR); hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR); hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR); DPRINTF(("bpp: hcr %x ocr %x tcr %x or %x\n", hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or)); /* Set these to sane values */ hw->hw_hcr = ((ack_rate<<BPP_HCR_DSS_SHFT)&BPP_HCR_DSS_MASK) | ((ack_rate<<BPP_HCR_DSW_SHFT)&BPP_HCR_DSW_MASK); hw->hw_ocr |= BPP_OCR_ACK_OP; } }
void agtenattach(struct device *parent, struct device *self, void *args) { struct agten_softc *sc = (struct agten_softc *)self; struct sbus_attach_args *sa = args; bus_space_tag_t bt; bus_space_handle_t bh; int node, isconsole; char *nam; bt = sa->sa_bustag; node = sa->sa_node; nam = getpropstring(node, "model"); printf(": model %s", nam); isconsole = node == fbnode; /* * Map the various beasts of this card we are interested in. */ sc->sc_bustag = bt; sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); sc->sc_physoffset = (off_t)getpropint(node, "i128_fb_physaddr", 0x8000000); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + sc->sc_physoffset, getpropint(node, "i128_fb_size", 0x400000), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: couldn't map video memory\n", self->dv_xname); return; } sc->sc_i128_fb = bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + getpropint(node, "p9100_reg_physaddr", 0x10a0000), 0x4000, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: couldn't map control registers\n", self->dv_xname); return; } sc->sc_p9100 = bus_space_vaddr(bt, bh); /* * For some reason the agten does not use the canonical name for * properties, but uses an ffb_ prefix; and the linebytes property is * missing. * The following is a specific version of * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, BUS_SBUS); * using the correct property names. */ #ifdef notyet sc->sc_sunfb.sf_depth = 32; #else sc->sc_sunfb.sf_depth = getpropint(node, "ffb_depth", 8); #endif sc->sc_sunfb.sf_width = getpropint(node, "ffb_width", 1152); sc->sc_sunfb.sf_height = getpropint(node, "ffb_height", 900); sc->sc_sunfb.sf_linebytes = roundup(sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_depth) * sc->sc_sunfb.sf_depth / 8; sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes; printf(", %dx%d, depth %d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height, sc->sc_sunfb.sf_depth); sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_i128_fb; sc->sc_sunfb.sf_ro.ri_hw = sc; fbwscons_init(&sc->sc_sunfb, 0, isconsole); fbwscons_setcolormap(&sc->sc_sunfb, agten_setcolor); if (isconsole) fbwscons_console_init(&sc->sc_sunfb, -1); fbwscons_attach(&sc->sc_sunfb, &agten_accessops, isconsole); }
void timerattach_obio_4m(device_t parent, device_t self, void *aux) { union obio_attach_args *uoba = aux; struct sbus_attach_args *sa = &uoba->uoba_sbus; struct cpu_info *cpi; bus_space_handle_t bh; int i; CPU_INFO_ITERATOR n; if (sa->sa_nreg < 2) { printf(": only %d register sets\n", sa->sa_nreg); return; } /* Map the system timer */ i = sa->sa_nreg - 1; if (bus_space_map2(sa->sa_bustag, BUS_ADDR(sa->sa_reg[i].oa_space, sa->sa_reg[i].oa_base), sizeof(struct timer_4m), BUS_SPACE_MAP_LINEAR, TIMERREG_VA, &bh) != 0) { printf(": can't map registers\n"); return; } timerreg4m = (struct timer_4m *)TIMERREG_VA; /* Map each CPU's counter */ for (i = 0; i < sa->sa_nreg - 1; i++) { /* * Check whether the CPU corresponding to this timer * register is installed. */ for (CPU_INFO_FOREACH(n, cpi)) { if ((i == 0 && sparc_ncpus == 1) || cpi->mid == i + 8) { /* We got a corresponding MID. */ break; } cpi = NULL; } if (cpi == NULL) continue; if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[i].oa_space, sa->sa_reg[i].oa_base, sizeof(struct timer_4m), BUS_SPACE_MAP_LINEAR, &bh) != 0) { printf(": can't map CPU counter %d\n", i); return; } cpi->counterreg_4m = (struct counter_4m *)bh; } #if defined(MULTIPROCESSOR) if (sparc_ncpus > 1) { /* * Note that we don't actually use this cookie after checking * it was establised, we call directly via raise_ipi() on * IPL_HARDCLOCK. */ void *hardclock_cookie; hardclock_cookie = sparc_softintr_establish(IPL_HARDCLOCK, hardclock_ipi, NULL); if (hardclock_cookie == NULL) panic("timerattach: cannot establish hardclock_intr"); } #endif /* Put processor counter in "timer" mode */ timerreg4m->t_cfg = 0; timerattach(&timerreg4m->t_counter, &timerreg4m->t_limit); }
void magma_attach(device_t parent, device_t self, void *aux) { struct sbus_attach_args *sa = aux; struct magma_softc *sc = device_private(self); struct magma_board_info *card; bus_space_handle_t bh; char *magma_prom, *clockstr; int cd_clock; int node, chip; sc->ms_dev = self; node = sa->sa_node; /* * Find the card model. * Older models all have sbus node name `MAGMA_Sp' (see * `supported_cards[]' above), and must be distinguished * by the `magma_prom' property. */ magma_prom = prom_getpropstring(node, "magma_prom"); for (card = supported_cards; card->mb_name != NULL; card++) { if (strcmp(sa->sa_name, card->mb_sbusname) != 0) /* Sbus node name doesn't match */ continue; if (strcmp(magma_prom, card->mb_name) == 0) /* Model name match */ break; } if( card->mb_name == NULL ) { printf(": %s (unsupported)\n", magma_prom); return; } dprintf((" addr %p", sc)); printf(": %s\n", card->mb_realname); sc->ms_board = card; sc->ms_ncd1400 = card->mb_ncd1400; sc->ms_ncd1190 = card->mb_ncd1190; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error("%s @ sbus: cannot map registers\n", device_xname(self)); return; } /* the SVCACK* lines are daisychained */ sc->ms_svcackr = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_svcackr; sc->ms_svcackt = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_svcackt; sc->ms_svcackm = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_svcackm; /* * Find the clock speed; it's the same for all CD1400 chips * on the board. */ clockstr = prom_getpropstring(node, "clock"); if (*clockstr == '\0') /* Default to 25MHz */ cd_clock = 25; else { cd_clock = 0; while (*clockstr != '\0') cd_clock = (cd_clock * 10) + (*clockstr++ - '0'); } /* init the cd1400 chips */ for( chip = 0 ; chip < card->mb_ncd1400 ; chip++ ) { struct cd1400 *cd = &sc->ms_cd1400[chip]; cd->cd_clock = cd_clock; cd->cd_reg = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_cd1400[chip]; /* prom_getpropstring(node, "chiprev"); */ /* seemingly the Magma drivers just ignore the propstring */ cd->cd_chiprev = cd1400_read_reg(cd, CD1400_GFRCR); dprintf(("%s attach CD1400 %d addr %p rev %x clock %dMHz\n", device_xname(sc->ms_dev), chip, cd->cd_reg, cd->cd_chiprev, cd->cd_clock)); /* clear GFRCR */ cd1400_write_reg(cd, CD1400_GFRCR, 0x00); /* reset whole chip */ cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); /* wait for revision code to be restored */ while( cd1400_read_reg(cd, CD1400_GFRCR) != cd->cd_chiprev ) ; /* set the Prescaler Period Register to tick at 1ms */ cd1400_write_reg(cd, CD1400_PPR, ((cd->cd_clock * 1000000 / CD1400_PPR_PRESCALER + 500) / 1000)); /* The LC2+1Sp card is the only card that doesn't have * a CD1190 for the parallel port, but uses channel 0 of * the CD1400, so we make a note of it for later and set up * the CD1400 for parallel mode operation. */ if( card->mb_npar && card->mb_ncd1190 == 0 ) { cd1400_write_reg(cd, CD1400_GCR, CD1400_GCR_PARALLEL); cd->cd_parmode = 1; } } /* init the cd1190 chips */ for( chip = 0 ; chip < card->mb_ncd1190 ; chip++ ) { struct cd1190 *cd = &sc->ms_cd1190[chip]; cd->cd_reg = (char *)bus_space_vaddr(sa->sa_bustag, bh) + card->mb_cd1190[chip]; /* XXX don't know anything about these chips yet */ printf("%s: CD1190 %d addr %p (unsupported)\n", device_xname(self), chip, cd->cd_reg); } /* configure the children */ (void)config_found(self, mtty_match, NULL); (void)config_found(self, mbpp_match, NULL); /* * Establish the interrupt handlers. */ if (sa->sa_nintr == 0) return; /* No interrupts to service!? */ (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_SERIAL, magma_hard, sc); sc->ms_sicookie = softint_establish(SOFTINT_SERIAL, magma_soft, sc); if (sc->ms_sicookie == NULL) { aprint_normal("\n"); aprint_error_dev(sc->ms_dev, "cannot establish soft int handler\n"); return; } evcnt_attach_dynamic(&sc->ms_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(sc->ms_dev), "intr"); }
void leattach_ledma(device_t parent, device_t self, void *aux) { struct le_softc *lesc = device_private(self); struct lance_softc *sc = &lesc->sc_am7990.lsc; struct lsi64854_softc *lsi = device_private(parent); struct sbus_attach_args *sa = aux; bus_dma_tag_t dmatag = sa->sa_dmatag; bus_dma_segment_t seg; int rseg, error; sc->sc_dev = self; lesc->sc_bustag = sa->sa_bustag; /* Establish link to `ledma' device */ lesc->sc_dma = lsi; lesc->sc_dma->sc_client = lesc; /* Map device registers */ if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &lesc->sc_reg) != 0) { aprint_error(": cannot map registers\n"); return; } /* Allocate buffer memory */ sc->sc_memsize = MEMSIZE; /* Get a DMA handle */ if ((error = bus_dmamap_create(dmatag, MEMSIZE, 1, MEMSIZE, LEDMA_BOUNDARY, BUS_DMA_NOWAIT, &lesc->sc_dmamap)) != 0) { aprint_error(": DMA map create error %d\n", error); return; } /* Allocate DMA buffer */ if ((error = bus_dmamem_alloc(dmatag, MEMSIZE, 0, LEDMA_BOUNDARY, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { aprint_error(": DMA buffer alloc error %d\n",error); return; } /* Map DMA buffer into kernel space */ if ((error = bus_dmamem_map(dmatag, &seg, rseg, MEMSIZE, (void **)&sc->sc_mem, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error(": DMA buffer map error %d\n", error); bus_dmamem_free(dmatag, &seg, rseg); return; } /* Load DMA buffer */ if ((error = bus_dmamap_load(dmatag, lesc->sc_dmamap, sc->sc_mem, MEMSIZE, NULL, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error(": DMA buffer map load error %d\n", error); bus_dmamem_free(dmatag, &seg, rseg); bus_dmamem_unmap(dmatag, sc->sc_mem, MEMSIZE); return; } lesc->sc_laddr = lesc->sc_dmamap->dm_segs[0].ds_addr; sc->sc_addr = lesc->sc_laddr & 0xffffff; sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; /* Assume SBus is grandparent */ lesc->sc_sd.sd_reset = (void *)lance_reset; sbus_establish(&lesc->sc_sd, parent); sc->sc_mediachange = lemediachange; sc->sc_mediastatus = lemediastatus; sc->sc_supmedia = lemedia; sc->sc_nsupmedia = NLEMEDIA; sc->sc_defaultmedia = IFM_ETHER|IFM_AUTO; prom_getether(sa->sa_node, sc->sc_enaddr); sc->sc_copytodesc = lance_copytobuf_contig; sc->sc_copyfromdesc = lance_copyfrombuf_contig; sc->sc_copytobuf = lance_copytobuf_contig; sc->sc_copyfrombuf = lance_copyfrombuf_contig; sc->sc_zerobuf = lance_zerobuf_contig; sc->sc_rdcsr = lerdcsr; sc->sc_wrcsr = lewrcsr; sc->sc_hwinit = lehwinit; sc->sc_nocarrier = lenocarrier; sc->sc_hwreset = lehwreset; /* Establish interrupt handler */ if (sa->sa_nintr != 0) (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, am7990_intr, sc); am7990_config(&lesc->sc_am7990); /* now initialize DMA */ lehwreset(sc); }
/* * Attach and initialize a rfx display, as well as a child wsdisplay. */ void rfxattach(struct device *parent, struct device *self, void *args) { struct rfx_softc *sc = (struct rfx_softc *)self; struct sbus_attach_args *sa = args; const char *device = sa->sa_name; struct rfx_config cf; bus_space_tag_t bt; bus_space_handle_t bh; int node, cflen, isconsole = 0; /* skip vendor name (could be CWARE, VITec, ...) */ while (*device != ',' && *device != '\0') device++; if (*device == '\0') device = sa->sa_name; else device++; printf(": %s", device); if (sa->sa_nreg == 0) { printf("\n%s: no SBus registers!\n", self->dv_xname); return; } bt = sa->sa_bustag; node = sa->sa_node; isconsole = node == fbnode; /* * Parse configuration structure */ cflen = getproplen(node, "configuration"); if (cflen != sizeof cf) { printf(", unknown %d bytes conf. structure", cflen); /* fill in default values */ cf.version = 0; cf.scanline = 2048; cf.width = 1152; cf.height = 900; } else { OF_getprop(node, "configuration", &cf, cflen); printf(", revision %d", cf.version); } /* * Map registers */ sc->sc_bustag = bt; sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_RAMDAC_ADDR, RFX_RAMDAC_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: couldn't map ramdac registers\n", self->dv_xname); return; } sc->sc_ramdac = (u_int8_t *)bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_CONTROL_ADDR, RFX_CONTROL_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: couldn't map control registers\n", self->dv_xname); return; } sc->sc_ctrl = (u_int32_t *)bus_space_vaddr(bt, bh); #if 0 /* not yet */ sc->sc_ih.ih_fun = rfx_intr; sc->sc_ih.ih_arg = sc; intr_establish(ca->ca_ra.ra_intr[0].int_pri, &sc->sc_ih, IPL_FB); #endif /* * The following is an equivalent for * fb_setsize(&sc->sc_sunfb, 8, cf.width, cf.height, * node, ca->ca_bustype); * forcing the correct scan line value. Since the usual frame buffer * properties are missing on this card, no need to go through * fb_setsize()... */ sc->sc_sunfb.sf_depth = 8; sc->sc_sunfb.sf_width = cf.width; sc->sc_sunfb.sf_height = cf.height; sc->sc_sunfb.sf_linebytes = cf.scanline; sc->sc_sunfb.sf_fbsize = cf.height * cf.scanline; printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + RFX_VRAM_ADDR, round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: couldn't map video memory\n", self->dv_xname); return; } sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh); sc->sc_sunfb.sf_ro.ri_hw = sc; /* * If we are not the console, the frame buffer has not been * initialized by the PROM - do this ourselves. */ if (!isconsole) { if (rfx_initialize(sc, sa, &cf) != 0) return; } fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR); bzero(&sc->sc_cmap, sizeof(sc->sc_cmap)); fbwscons_setcolormap(&sc->sc_sunfb, rfx_setcolor); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, -1); } /* enable video */ rfx_burner(sc, 1, 0); fbwscons_attach(&sc->sc_sunfb, &rfx_accessops, isconsole); }
void zx_attach(struct device *parent, struct device *self, void *args) { struct zx_softc *sc = (struct zx_softc *)self; struct sbus_attach_args *sa = args; struct rasops_info *ri; bus_space_tag_t bt; bus_space_handle_t bh; int node, isconsole = 0; const char *nam; bt = sa->sa_bustag; ri = &sc->sc_sunfb.sf_ro; node = sa->sa_node; /* * Map the various parts of the card. */ sc->sc_bustag = bt; sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR, sizeof(struct zx_command), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf(": couldn't map command registers\n"); return; } sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0, sizeof(struct zx_draw), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf(": couldn't map ss0 drawing registers\n"); return; } sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1, sizeof(struct zx_draw_ss1), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf(": couldn't map ss1 drawing registers\n"); return; } sc->sc_zd_ss1 = (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS, sizeof(struct zx_cross), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf(": couldn't map cross registers\n"); return; } sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR, sizeof(struct zx_cursor), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf(": couldn't map cursor registers\n"); return; } sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh); nam = getpropstring(node, "model"); if (*nam == '\0') nam = sa->sa_name; printf(": %s", nam); isconsole = node == fbnode; /* * The console is using the 8-bit overlay plane, while the prom * will correctly report 32 bit depth. * The following is an equivalent for * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); * forcing the depth value not to be overwritten. * Furthermore, the linebytes value is in fact 8192 bytes. */ sc->sc_sunfb.sf_depth = 8; sc->sc_sunfb.sf_width = getpropint(node, "width", 1152); sc->sc_sunfb.sf_height = getpropint(node, "height", 900); sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH; sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH; printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0, round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("%s: couldn't map video memory\n", self->dv_xname); return; } ri->ri_bits = bus_space_vaddr(bt, bh); ri->ri_hw = sc; fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR); /* * Watch out! rasops_init() invoked via fbwscons_init() did not * compute ri_bits correctly when centering the display, because * it has been tricked with the low depth value. * Recompute now. */ ri->ri_emustride = ri->ri_emuwidth * 4; ri->ri_delta = ri->ri_stride - ri->ri_emustride; ri->ri_pelbytes = 4; ri->ri_xscale = ri->ri_font->fontwidth * 4; ri->ri_bits = ri->ri_origbits; ri->ri_bits += (((ri->ri_width * 4) - ri->ri_emustride) >> 1) & ~3; ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) * ri->ri_stride; ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) / ri->ri_stride; ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) % ri->ri_stride) / 4); ri->ri_ops.copyrows = zx_copyrows; ri->ri_ops.copycols = zx_copycols; ri->ri_ops.eraserows = zx_eraserows; ri->ri_ops.erasecols = zx_erasecols; ri->ri_ops.putchar = zx_putchar; ri->ri_do_cursor = zx_do_cursor; if (isconsole) { /* zx_reset() below will clear screen, so restart at 1st row */ fbwscons_console_init(&sc->sc_sunfb, 0); } /* reset cursor & frame buffer controls */ zx_reset(sc, WSDISPLAYIO_MODE_EMUL); /* enable video */ zx_burner(sc, 1, 0); fbwscons_attach(&sc->sc_sunfb, &zx_accessops, isconsole); }
/* * Attach a display. We need to notice if it is the console, too. */ static void p9100_sbus_attach(struct device *parent, struct device *self, void *args) { struct p9100_softc *sc = device_private(self); struct sbus_attach_args *sa = args; struct fbdevice *fb = &sc->sc_fb; int isconsole; int node; int i, j; uint8_t ver; #if NWSDISPLAY > 0 struct wsemuldisplaydev_attach_args aa; struct rasops_info *ri; unsigned long defattr; #endif sc->sc_last_offset = 0xffffffff; /* Remember cookies for p9100_mmap() */ sc->sc_bustag = sa->sa_bustag; sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base); sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/ sc->sc_cmd_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base); sc->sc_cmd_psize = (bus_size_t)sa->sa_reg[1].oa_size; sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base); sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size; fb->fb_driver = &p9100fbdriver; fb->fb_device = &sc->sc_dev; fb->fb_flags = device_cfdata(&sc->sc_dev)->cf_flags & FB_USERMASK; #ifdef PNOZZ_EMUL_CG3 fb->fb_type.fb_type = FBTYPE_SUN3COLOR; #else fb->fb_type.fb_type = FBTYPE_P9100; #endif fb->fb_pixels = NULL; sc->sc_mode = WSDISPLAYIO_MODE_EMUL; node = sa->sa_node; isconsole = fb_is_console(node); if (!isconsole) { aprint_normal("\n"); aprint_error_dev(self, "fatal error: PROM didn't configure device\n"); return; } /* * When the ROM has mapped in a p9100 display, the address * maps only the video RAM, so in any case we have to map the * registers ourselves. We only need the video RAM if we are * going to print characters via rconsole. */ if (sbus_bus_map(sc->sc_bustag, sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base, /* * XXX for some reason the SBus resources don't cover * all registers, so we just map what we need */ /*sc->sc_ctl_psize*/ 0x8000, /*BUS_SPACE_MAP_LINEAR*/0, &sc->sc_ctl_memh) != 0) { aprint_error_dev(self, "cannot map control registers\n"); return; } if (sa->sa_npromvaddrs != 0) fb->fb_pixels = (void *)sa->sa_promvaddrs[0]; if (fb->fb_pixels == NULL) { if (sbus_bus_map(sc->sc_bustag, sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base, sc->sc_fb_psize, BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) { aprint_error_dev(self, "cannot map framebuffer\n"); return; } fb->fb_pixels = (char *)sc->sc_fb_memh; } else { sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels; } i = p9100_ctl_read_4(sc, 0x0004); switch ((i >> 26) & 7) { case 5: fb->fb_type.fb_depth = 32; break; case 7: fb->fb_type.fb_depth = 24; break; case 3: fb->fb_type.fb_depth = 16; break; case 2: fb->fb_type.fb_depth = 8; break; default: { panic("pnozz: can't determine screen depth (0x%02x)", i); } } sc->sc_depth = (fb->fb_type.fb_depth >> 3); /* XXX for some reason I get a kernel trap with this */ sc->sc_width = prom_getpropint(node, "width", 800); sc->sc_height = prom_getpropint(node, "height", 600); sc->sc_stride = prom_getpropint(node, "linebytes", sc->sc_width * (fb->fb_type.fb_depth >> 3)); /* check the RAMDAC */ ver = p9100_ramdac_read_ctl(sc, DAC_VERSION); p9100_init_engine(sc); fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height, node); sbus_establish(&sc->sc_sd, &sc->sc_dev); bus_intr_establish(sc->sc_bustag, sa->sa_pri, IPL_BIO, p9100_intr, sc); fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; printf(": rev %d / %x, %dx%d, depth %d mem %x", (i & 7), ver, fb->fb_type.fb_width, fb->fb_type.fb_height, fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize); fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256); if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize) printf(", %d entry colormap", fb->fb_type.fb_cmsize); /* Initialize the default color map. */ /*bt_initcmap(&sc->sc_cmap, 256);*/ j = 0; for (i = 0; i < 256; i++) { sc->sc_cmap.cm_map[i][0] = rasops_cmap[j]; j++; sc->sc_cmap.cm_map[i][1] = rasops_cmap[j]; j++; sc->sc_cmap.cm_map[i][2] = rasops_cmap[j]; j++; } p9100loadcmap(sc, 0, 256); /* make sure we are not blanked */ if (isconsole) p9100_set_video(sc, 1); if (shutdownhook_establish(p9100_shutdown, sc) == NULL) { panic("%s: could not establish shutdown hook", device_xname(&sc->sc_dev)); } if (isconsole) { printf(" (console)\n"); #ifdef RASTERCONSOLE /*p9100loadcmap(sc, 255, 1);*/ fbrcons_init(fb); #endif } else printf("\n"); #if NWSDISPLAY > 0 wsfont_init(); vcons_init(&sc->vd, sc, &p9100_defscreendesc, &p9100_accessops); sc->vd.init_screen = p9100_init_screen; vcons_init_screen(&sc->vd, &p9100_console_screen, 1, &defattr); p9100_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; sc->sc_bg = (defattr >> 16) & 0xff; p9100_clearscreen(sc); ri = &p9100_console_screen.scr_ri; p9100_defscreendesc.nrows = ri->ri_rows; p9100_defscreendesc.ncols = ri->ri_cols; p9100_defscreendesc.textops = &ri->ri_ops; p9100_defscreendesc.capabilities = ri->ri_caps; if(isconsole) { wsdisplay_cnattach(&p9100_defscreendesc, ri, 0, 0, defattr); } aa.console = isconsole; aa.scrdata = &p9100_screenlist; aa.accessops = &p9100_accessops; aa.accesscookie = &sc->vd; config_found(self, &aa, wsemuldisplaydevprint); #endif /* cursor sprite handling */ p9100_init_cursor(sc); /* attach the fb */ fb_attach(fb, isconsole); /* register with power management */ sc->sc_video = 1; sc->sc_powerstate = PWR_RESUME; powerhook_establish(device_xname(&sc->sc_dev), p9100_power_hook, sc); #if NTCTRL > 0 /* register callback for external monitor status change */ tadpole_register_callback(p9100_set_extvga, sc); #endif }
static void tctrl_attach(device_t parent, device_t self, void *aux) { struct tctrl_softc *sc = device_private(self); union obio_attach_args *uoba = aux; struct sbus_attach_args *sa = &uoba->uoba_sbus; unsigned int i, v; /* We're living on a sbus slot that looks like an obio that * looks like an sbus slot. */ sc->sc_dev = self; sc->sc_memt = sa->sa_bustag; if (sbus_bus_map(sc->sc_memt, sa->sa_slot, sa->sa_offset - TS102_REG_UCTRL_INT, sa->sa_size, BUS_SPACE_MAP_LINEAR, &sc->sc_memh) != 0) { printf(": can't map registers\n"); return; } printf("\n"); sc->sc_tft_on = 1; /* clear any pending data. */ for (i = 0; i < 10000; i++) { if ((TS102_UCTRL_STS_RXNE_STA & tctrl_read(sc, TS102_REG_UCTRL_STS)) == 0) { break; } v = tctrl_read(sc, TS102_REG_UCTRL_DATA); tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA); } if (sa->sa_nintr != 0) { (void)bus_intr_establish(sc->sc_memt, sa->sa_pri, IPL_NONE, tctrl_intr, sc); evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(sc->sc_dev), "intr"); } /* See what the external status is */ sc->sc_ext_status = 0; tctrl_read_ext_status(); if (sc->sc_ext_status != 0) { const char *sep; printf("%s: ", device_xname(sc->sc_dev)); v = sc->sc_ext_status; for (i = 0, sep = ""; v != 0; i++, v >>= 1) { if (v & 1) { printf("%s%s", sep, tctrl_ext_statuses[i]); sep = ", "; } } printf("\n"); } /* Get a current of the control bitport */ tctrl_setup_bitport_nop(); tctrl_write(sc, TS102_REG_UCTRL_INT, TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK); sc->sc_lid = (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) == 0; sc->sc_power_state = PWR_RESUME; sc->sc_extvga = (sc->sc_ext_status & TS102_EXT_STATUS_EXTERNAL_VGA_ATTACHED) != 0; sc->sc_video_callback = NULL; sc->sc_wantdata = 0; sc->sc_event_count = 0; sc->sc_ext_pending = 0; sc->sc_ext_pending = 0; mutex_init(&sc->sc_requestlock, MUTEX_DEFAULT, IPL_NONE); selinit(&sc->sc_rsel); /* setup sensors and register the power button */ tctrl_sensor_setup(sc); tctrl_lid_state(sc); tctrl_ac_state(sc); /* initialize the LCD */ tctrl_init_lcd(); /* initialize sc_lcdstate */ sc->sc_lcdstate = 0; sc->sc_lcdwanted = 0; tadpole_set_lcd(2, 0); /* fire up the LCD event thread */ sc->sc_events = 0; if (kthread_create(PRI_NONE, 0, NULL, tctrl_event_thread, sc, &sc->sc_thread, "%s", device_xname(sc->sc_dev)) != 0) { printf("%s: unable to create event kthread", device_xname(sc->sc_dev)); } }
/* * Attach all the sub-devices we can find */ void lebufattach(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa = aux; struct lebuf_softc *sc = (void *)self; int node; int sbusburst; struct sparc_bus_space_tag *sbt; bus_space_handle_t bh; sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("%s: attach: cannot map registers\n", self->dv_xname); return; } /* * This device's "register space" is just a buffer where the * Lance ring-buffers can be stored. Note the buffer's location * and size, so the `le' driver can pick them up. */ sc->sc_buffer = (void *)bus_space_vaddr(sa->sa_bustag, bh); sc->sc_bufsiz = sa->sa_size; node = sc->sc_node = sa->sa_node; /* * Get transfer burst size from PROM */ sbusburst = ((struct sbus_softc *)parent)->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ sc->sc_burst = getpropint(node, "burst-sizes", -1); if (sc->sc_burst == -1) /* take SBus burst sizes */ sc->sc_burst = sbusburst; /* Clamp at parent's burst sizes */ sc->sc_burst &= sbusburst; /* Allocate a bus tag */ sbt = malloc(sizeof(*sbt), M_DEVBUF, M_NOWAIT | M_ZERO); if (sbt == NULL) { printf("%s: attach: out of memory\n", self->dv_xname); return; } printf(": %dK memory\n", sc->sc_bufsiz / 1024); sbt->cookie = sc; sbt->parent = sc->sc_bustag; sbt->asi = sbt->parent->asi; sbt->sasi = sbt->parent->sasi; /* search through children */ for (node = firstchild(node); node; node = nextsibling(node)) { struct sbus_attach_args sa; sbus_setup_attach_args((struct sbus_softc *)parent, sbt, sc->sc_dmatag, node, &sa); (void)config_found(&sc->sc_dev, (void *)&sa, lebufprint); sbus_destroy_attach_args(&sa); } }
void bppattach(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa = aux; struct bpp_softc *dsc = (void *)self; struct lsi64854_softc *sc = &dsc->sc_lsi64854; int burst, sbusburst; int node; node = sa->sa_node; sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; /* Map device registers */ if (sa->sa_npromvaddrs != 0) { if (sbus_bus_map(sa->sa_bustag, 0, sa->sa_promvaddrs[0], sa->sa_size, /* ???? */ BUS_SPACE_MAP_PROMADDRESS, 0, &sc->sc_regs) != 0) { printf(": cannot map registers\n"); return; } } else if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, 0, &sc->sc_regs) != 0) { printf(": cannot map registers\n"); return; } /* Check for the interrupt property */ if (sa->sa_nintr == 0) { printf(": no interrupt property\n"); return; } /* * Get transfer burst size from PROM and plug it into the * controller registers. This is needed on the Sun4m; do * others need it too? */ sbusburst = ((struct sbus_softc *)parent)->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ burst = getpropint(node, "burst-sizes", -1); if (burst == -1) /* take SBus burst sizes */ burst = sbusburst; /* Clamp at parent's burst sizes */ burst &= sbusburst; sc->sc_burst = (burst & SBUS_BURST_32) ? 32 : (burst & SBUS_BURST_16) ? 16 : 0; /* Initialize the DMA channel */ sc->sc_channel = L64854_CHANNEL_PP; if (lsi64854_attach(sc) != 0) return; /* Establish interrupt handler */ sc->sc_intrchain = bppintr; sc->sc_intrchainarg = dsc; (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0, bppintr, sc, self->dv_xname); /* Allocate buffer XXX - should actually use dmamap_uio() */ dsc->sc_bufsz = 1024; dsc->sc_buf = malloc(dsc->sc_bufsz, M_DEVBUF, M_NOWAIT); /* XXX read default state */ { bus_space_handle_t h = sc->sc_regs; struct hwstate *hw = &dsc->sc_hwstate; int ack_rate = sa->sa_frequency/1000000; hw->hw_hcr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_HCR); hw->hw_ocr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_OCR); hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR); hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR); DPRINTF(("bpp: hcr %x ocr %x tcr %x or %x\n", hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or)); /* Set these to sane values */ hw->hw_hcr = ((ack_rate<<BPP_HCR_DSS_SHFT)&BPP_HCR_DSS_MASK) | ((ack_rate<<BPP_HCR_DSW_SHFT)&BPP_HCR_DSW_MASK); hw->hw_ocr |= BPP_OCR_ACK_OP; } }
/* * Attach a display. We need to notice if it is the console, too. */ static void genfb_attach_sbus(device_t parent, device_t self, void *args) { struct genfb_sbus_softc *sc = device_private(self); struct sbus_attach_args *sa = args; static const struct genfb_ops zero_ops; struct genfb_ops ops = zero_ops; prop_dictionary_t dict; bus_space_handle_t bh; paddr_t fbpa; vaddr_t fbva; int node = sa->sa_node; int isconsole; aprint_normal("\n"); sc->sc_gen.sc_dev = self; /* Remember cookies for genfb_mmap_sbus() */ sc->sc_tag = sa->sa_bustag; sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset); /* read geometry information from the device tree */ sc->sc_gen.sc_width = prom_getpropint(sa->sa_node, "width", 1152); sc->sc_gen.sc_height = prom_getpropint(sa->sa_node, "height", 900); sc->sc_gen.sc_depth = prom_getpropint(sa->sa_node, "depth", 8); sc->sc_gen.sc_stride = prom_getpropint(sa->sa_node, "linebytes", (sc->sc_gen.sc_width * sc->sc_gen.sc_depth + 7) >> 3 ); sc->sc_gen.sc_fbsize = sc->sc_gen.sc_height * sc->sc_gen.sc_stride; fbva = (uint32_t)prom_getpropint(sa->sa_node, "address", 0); if (fbva == 0) panic("this fb has no address property\n"); aprint_normal_dev(self, "%d x %d at %d bit\n", sc->sc_gen.sc_width, sc->sc_gen.sc_height, sc->sc_gen.sc_depth); pmap_extract(pmap_kernel(), fbva, &fbpa); sc->sc_gen.sc_fboffset = (fbpa & 0x01ffffff) - (sc->sc_paddr & 0x01ffffff); aprint_normal_dev(self, "framebuffer at offset 0x%x\n", (uint32_t)sc->sc_gen.sc_fboffset); #if notyet if (sc->sc_gen.sc_depth <= 8) { /* setup some ANSIish colour map */ char boo[256]; snprintf(boo, 256, "\" pal!\" %x %x %x %x %x call", sa->sa_node, 0, 0xa0, 0xa0, 0); prom_interpret(boo); } #endif isconsole = fb_is_console(node); dict = device_properties(self); prop_dictionary_set_bool(dict, "is_console", isconsole); if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset + sc->sc_gen.sc_fboffset, sc->sc_gen.sc_fbsize, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "cannot map framebuffer\n"); return; } sc->sc_gen.sc_fbaddr = (void *)bus_space_vaddr(sa->sa_bustag, bh); ops.genfb_ioctl = genfb_ioctl_sbus; ops.genfb_mmap = genfb_mmap_sbus; genfb_attach(&sc->sc_gen, &ops); }
static void zx_attach(device_t parent, device_t self, void *args) { struct zx_softc *sc; struct sbus_attach_args *sa; bus_space_handle_t bh; bus_space_tag_t bt; struct fbdevice *fb; #if NWSDISPLAY > 0 struct wsemuldisplaydev_attach_args aa; struct rasops_info *ri = &zx_console_screen.scr_ri; unsigned long defattr; #endif int isconsole, width, height; sc = device_private(self); sc->sc_dv = self; sa = args; fb = &sc->sc_fb; bt = sa->sa_bustag; sc->sc_bt = bt; sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0, 0x800000, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, &bh) != 0) { aprint_error_dev(self, "can't map bits\n"); return; } fb->fb_pixels = (void *)bus_space_vaddr(bt, bh); sc->sc_pixels = (uint32_t *)fb->fb_pixels; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map zc\n"); return; } sc->sc_bhzc = bh; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map ld/ss0\n"); return; } sc->sc_bhzdss0 = bh; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map ld/ss1\n"); return; } sc->sc_bhzdss1 = bh; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map zx\n"); return; } sc->sc_bhzx = bh; if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { aprint_error_dev(self, "can't map zcu\n"); return; } sc->sc_bhzcu = bh; fb->fb_driver = &zx_fbdriver; fb->fb_device = sc->sc_dv; fb->fb_flags = device_cfdata(sc->sc_dv)->cf_flags & FB_USERMASK; fb->fb_pfour = NULL; fb->fb_linebytes = prom_getpropint(sa->sa_node, "linebytes", 8192); width = prom_getpropint(sa->sa_node, "width", 1280); height = prom_getpropint(sa->sa_node, "height", 1024); fb_setsize_obp(fb, 32, width, height, sa->sa_node); fb->fb_type.fb_cmsize = 256; fb->fb_type.fb_depth = 32; fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; fb->fb_type.fb_type = FBTYPE_SUNLEO; printf(": %d x %d", fb->fb_type.fb_width, fb->fb_type.fb_height); isconsole = fb_is_console(sa->sa_node); if (isconsole) printf(" (console)"); printf("\n"); if (sa->sa_nintr != 0) bus_intr_establish(bt, sa->sa_pri, IPL_NONE, zx_intr, sc); sc->sc_cmap = malloc(768, M_DEVBUF, M_NOWAIT); zx_reset(sc); #if NWSDISPLAY > 0 sc->sc_width = fb->fb_type.fb_width; sc->sc_stride = 8192; /* 32 bit */ sc->sc_height = fb->fb_type.fb_height; /* setup rasops and so on for wsdisplay */ wsfont_init(); sc->sc_mode = WSDISPLAYIO_MODE_EMUL; sc->sc_bg = WS_DEFAULT_BG; vcons_init(&sc->vd, sc, &zx_defaultscreen, &zx_accessops); sc->vd.init_screen = zx_init_screen; if (isconsole) { /* we mess with zx_console_screen only once */ vcons_init_screen(&sc->vd, &zx_console_screen, 1, &defattr); zx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; zx_defaultscreen.textops = &ri->ri_ops; zx_defaultscreen.capabilities = WSSCREEN_WSCOLORS; zx_defaultscreen.nrows = ri->ri_rows; zx_defaultscreen.ncols = ri->ri_cols; zx_fillrect(sc, 0, 0, width, height, ri->ri_devcmap[defattr >> 16], ZX_STD_ROP); wsdisplay_cnattach(&zx_defaultscreen, ri, 0, 0, defattr); vcons_replay_msgbuf(&zx_console_screen); } else { /* * we're not the console so we just clear the screen and don't * set up any sort of text display */ if (zx_defaultscreen.textops == NULL) {
void cs4231_attach(struct device *parent, struct device *self, void *aux) { struct sbus_attach_args *sa = aux; struct cs4231_softc *sc = (struct cs4231_softc *)self; int node; u_int32_t sbusburst, burst; node = sa->sa_node; /* Pass on the bus tags */ sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; /* Make sure things are sane. */ if (sa->sa_nintr != 1) { printf(": expected 1 interrupt, got %d\n", sa->sa_nintr); return; } if (sa->sa_nreg != 1) { printf(": expected 1 register set, got %d\n", sa->sa_nreg); return; } if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, 0, cs4231_intr, sc, self->dv_xname) == NULL) { printf(": couldn't establish interrupt, pri %d\n", INTLEV(sa->sa_pri)); return; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, (bus_addr_t)sa->sa_reg[0].sbr_offset, (bus_size_t)sa->sa_reg[0].sbr_size, BUS_SPACE_MAP_LINEAR, 0, &sc->sc_regs) != 0) { printf(": couldn't map registers\n"); return; } sbusburst = ((struct sbus_softc *)parent)->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ burst = getpropint(node, "burst-sizes", -1); if (burst == -1) burst = sbusburst; sc->sc_burst = burst & sbusburst; printf("\n"); audio_attach_mi(&cs4231_sa_hw_if, sc, &sc->sc_dev); /* Default to speaker, unmuted, reasonable volume */ sc->sc_out_port = CSPORT_SPEAKER; sc->sc_in_port = CSPORT_MICROPHONE; sc->sc_mute[CSPORT_SPEAKER] = 1; sc->sc_mute[CSPORT_MONITOR] = 1; sc->sc_volume[CSPORT_SPEAKER].left = 192; sc->sc_volume[CSPORT_SPEAKER].right = 192; }
void spif_attach(device_t parent, device_t self, void *aux) { struct spif_softc *sc = device_private(self); struct sbus_attach_args *sa = aux; sc->sc_dev = self; if (sa->sa_nintr != 2) { printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr); return; } if (sa->sa_nreg != 1) { printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); return; } sc->sc_bustag = sa->sa_bustag; if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &sc->sc_regh) != 0) { printf(": can't map registers\n"); return; } if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) { printf(": can't map dtr regs\n"); goto fail_unmapregs; } if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) { printf(": can't map dtr regs\n"); goto fail_unmapregs; } if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) { printf(": can't map dtr regs\n"); goto fail_unmapregs; } if (bus_space_subregion(sc->sc_bustag, sc->sc_regh, PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) { printf(": can't map dtr regs\n"); goto fail_unmapregs; } sc->sc_ppcih = bus_intr_establish(sa->sa_bustag, sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc); if (sc->sc_ppcih == NULL) { printf(": failed to establish ppc interrupt\n"); goto fail_unmapregs; } sc->sc_stcih = bus_intr_establish(sa->sa_bustag, sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc); if (sc->sc_stcih == NULL) { printf(": failed to establish stc interrupt\n"); goto fail_unmapregs; } sc->sc_softih = softint_establish(SOFTINT_SERIAL, spif_softintr, sc); if (sc->sc_softih == NULL) { printf(": can't get soft intr\n"); goto fail_unmapregs; } sc->sc_node = sa->sa_node; sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0); sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0); switch (sc->sc_osc) { case SPIF_OSC10: sc->sc_osc = 10000000; break; case SPIF_OSC9: default: sc->sc_osc = 9830400; break; } sc->sc_nser = 8; sc->sc_npar = 1; sc->sc_rev2 = STC_READ(sc, STC_GFRCR); STC_WRITE(sc, STC_GSVR, 0); stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL); while (STC_READ(sc, STC_GSVR) != 0xff); while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2); STC_WRITE(sc, STC_PPRH, CD180_PPRH); STC_WRITE(sc, STC_PPRL, CD180_PPRL); STC_WRITE(sc, STC_MSMR, SPIF_MSMR); STC_WRITE(sc, STC_TSMR, SPIF_TSMR); STC_WRITE(sc, STC_RSMR, SPIF_RSMR); STC_WRITE(sc, STC_GSVR, 0); STC_WRITE(sc, STC_GSCR1, 0); STC_WRITE(sc, STC_GSCR2, 0); STC_WRITE(sc, STC_GSCR3, 0); printf(": rev %x chiprev %x osc %sMHz\n", sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc)); (void)config_found(self, stty_match, NULL); (void)config_found(self, sbpp_match, NULL); return; fail_unmapregs: bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size); }
/* * Attach an MGX frame buffer. * This will keep the frame buffer in the actual PROM mode, and attach * a wsdisplay child device to itself. */ void mgxattach(struct device *parent, struct device *self, void *args) { struct mgx_softc *sc = (struct mgx_softc *)self; struct sbus_attach_args *sa = args; bus_space_tag_t bt; bus_space_handle_t bh; int node, fbsize; int isconsole; uint16_t chipid; bt = sa->sa_bustag; node = sa->sa_node; printf(": %s", getpropstring(node, "model")); isconsole = node == fbnode; /* Check registers */ if (sa->sa_nreg < MGX_NREG) { printf("\n%s: expected %d registers, got %d\n", self->dv_xname, MGX_NREG, sa->sa_nreg); return; } sc->sc_bustag = bt; if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_CRTC].sbr_slot, sa->sa_reg[MGX_REG_CRTC].sbr_offset, PAGE_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: couldn't map crtc registers\n", self->dv_xname); return; } sc->sc_vidc = (vaddr_t)bus_space_vaddr(bt, bh); sc->sc_bustag = bt; if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_ATREG].sbr_slot, sa->sa_reg[MGX_REG_ATREG].sbr_offset + MGX_REG_ATREG_OFFSET, MGX_REG_ATREG_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: couldn't map crtc registers\n", self->dv_xname); /* XXX unmap vidc */ return; } sc->sc_xreg = (vaddr_t)bus_space_vaddr(bt, bh); /* * Check the chip ID. If it's not an AT24, prefer not to access * the extended registers at all. */ chipid = mgx_read_2(sc->sc_xreg, ATR_ID); if (chipid != ID_AT24) { sc->sc_xreg = (vaddr_t)0; } /* enable video */ mgx_burner(sc, 1, 0); fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); /* Sanity check frame buffer memory */ fbsize = getpropint(node, "fb_size", 0); if (fbsize != 0 && sc->sc_sunfb.sf_fbsize > fbsize) { printf("\n%s: expected at least %d bytes of vram, but card " "only provides %d\n", self->dv_xname, sc->sc_sunfb.sf_fbsize, fbsize); return; } /* Map the frame buffer memory area we're interested in */ sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot, sa->sa_reg[MGX_REG_VRAM8].sbr_offset); if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot, sa->sa_reg[MGX_REG_VRAM8].sbr_offset, round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: couldn't map video memory\n", self->dv_xname); /* XXX unmap vidc and xreg */ return; } sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh); sc->sc_sunfb.sf_ro.ri_hw = sc; printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); fbwscons_init(&sc->sc_sunfb, 0, isconsole); bzero(sc->sc_cmap, sizeof(sc->sc_cmap)); fbwscons_setcolormap(&sc->sc_sunfb, mgx_setcolor); if (chipid != ID_AT24) { printf("%s: unexpected engine id %04x\n", self->dv_xname, chipid); } mgx_ras_init(sc, chipid); if (isconsole) fbwscons_console_init(&sc->sc_sunfb, -1); fbwscons_attach(&sc->sc_sunfb, &mgx_accessops, isconsole); }
static void com_obio_attach(device_t parent, device_t self, void *aux) { struct com_obio_softc *osc = device_private(self); struct com_softc *sc = &osc->osc_com; union obio_attach_args *uoba = aux; struct sbus_attach_args *sa = &uoba->uoba_sbus; bus_space_handle_t ioh; bus_space_tag_t iot; bus_addr_t iobase; sc->sc_dev = self; if (strcmp("modem", sa->sa_name) == 0) { osc->osc_tadpole = 1; } /* * We're living on an obio that looks like an sbus slot. */ iot = sa->sa_bustag; iobase = sa->sa_offset; sc->sc_frequency = COM_FREQ; /* * XXX: It would be nice to be able to split console input and * output to different devices. For now switch to serial * console if PROM stdin is on serial (so that we can use DDB). */ if (prom_instance_to_package(prom_stdin()) == sa->sa_node) comcnattach(iot, iobase, B9600, sc->sc_frequency, COM_TYPE_NORMAL, (CLOCAL | CREAD | CS8)); if (!com_is_console(iot, iobase, &ioh) && sbus_bus_map(iot, sa->sa_slot, iobase, sa->sa_size, BUS_SPACE_MAP_LINEAR, &ioh) != 0) { aprint_error(": can't map registers\n"); return; } COM_INIT_REGS(sc->sc_regs, iot, ioh, iobase); if (osc->osc_tadpole) { *AUXIO4M_REG |= (AUXIO4M_LED|AUXIO4M_LTE); do { DELAY(100); } while (!com_probe_subr(&sc->sc_regs)); #if 0 printf("modem: attach: lcr=0x%02x iir=0x%02x\n", bus_space_read_1(sc->sc_regs.iot, sc->sc_regs.ioh, 3), bus_space_read_1(sc->sc_regs.iot, sc->sc_regs.ioh, 2)); #endif } com_attach_subr(sc); if (sa->sa_nintr != 0) { (void)bus_intr_establish(sc->sc_regs.cr_iot, sa->sa_pri, IPL_SERIAL, comintr, sc); evcnt_attach_dynamic(&osc->osc_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(self), "intr"); } if (!pmf_device_register1(self, com_suspend, com_resume, com_cleanup)) { aprint_error_dev(self, "could not establish shutdown hook"); } }
/* * Attach and initialize a cgtwelve. */ void cgtwelveattach(struct device *parent, struct device *self, void *args) { struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self; struct sbus_attach_args *sa = args; bus_space_tag_t bt; bus_space_handle_t bh; int node, isconsole = 0; char *ps; bt = sa->sa_bustag; node = sa->sa_node; printf(": %s", getpropstring(node, "model")); ps = getpropstring(node, "dev_id"); if (*ps != '\0') printf(" (%s)", ps); printf("\n"); isconsole = node == fbnode; if (sa->sa_nreg == 0) { printf("%s: no SBus registers!\n", self->dv_xname); return; } sc->sc_bustag = bt; /* * Map registers */ if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + CG12_OFF_DPU, sizeof(struct cgtwelve_dpu), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("%s: can't map DPU registers\n", self->dv_xname); return; } sc->sc_dpu = bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + CG12_OFF_APU, sizeof(struct cgtwelve_apu), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("%s: can't map APU registers\n", self->dv_xname); return; } sc->sc_apu = bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + CG12_OFF_DAC, sizeof(struct cgtwelve_dac), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("%s: can't map RAMDAC registers\n", self->dv_xname); return; } sc->sc_ramdac = bus_space_vaddr(bt, bh); /* * The console is using the 1-bit overlay plane, while the prom * will correctly report 32 bit depth. */ fb_setsize(&sc->sc_sunfb, 1, CG12_WIDTH, CG12_HEIGHT, node, 0); sc->sc_sunfb.sf_depth = 1; sc->sc_sunfb.sf_linebytes = sc->sc_sunfb.sf_width / 8; sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes; sc->sc_highres = sc->sc_sunfb.sf_width == CG12_WIDTH_HR; /* * Map planes */ if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + (sc->sc_highres ? CG12_OFF_OVERLAY0_HR : CG12_OFF_OVERLAY0), round_page(sc->sc_highres ? CG12_SIZE_OVERLAY_HR : CG12_SIZE_OVERLAY), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("%s: can't map overlay plane\n", self->dv_xname); return; } sc->sc_overlay = bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + (sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN), round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR : CG12_SIZE_COLOR24), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("%s: can't map color plane\n", self->dv_xname); return; } sc->sc_inten = bus_space_vaddr(bt, bh); sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset + (sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN)); /* reset cursor & frame buffer controls */ sc->sc_sunfb.sf_depth = 0; /* force action */ cgtwelve_reset(sc, 1); sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_overlay; sc->sc_sunfb.sf_ro.ri_hw = sc; fbwscons_init(&sc->sc_sunfb, 0, isconsole); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, -1); shutdownhook_establish(cgtwelve_prom, sc); } printf("%s: %dx%d", self->dv_xname, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); ps = getpropstring(node, "ucoderev"); if (*ps != '\0') printf(", microcode rev. %s", ps); printf("\n"); fbwscons_attach(&sc->sc_sunfb, &cgtwelve_accessops, isconsole); }
void qla_sbus_attach(struct device *parent, struct device *self, void *aux) { struct qla_softc *sc = (void *)self; struct sbus_attach_args *sa = aux; struct sparc_bus_space_tag *iot; bus_space_handle_t ioh; pcireg_t id, class; char devinfo[256]; if (sa->sa_nintr < 1) { printf(": no interrupt\n"); return; } if (sa->sa_nreg < 1) { printf(": no registers\n"); return; } /* * These cards have a standard PCI chips that sit behind an * FPGA with some bridging logic. Since the PCI bus is * little-endian, we need a little-endian bus tag. So we * build one here. */ iot = malloc(sizeof(*iot), M_DEVBUF, M_NOWAIT); if (iot == NULL) { printf(": can't allocate bus tag\n"); return; } *iot = *sa->sa_bustag; iot->asi = ASI_PRIMARY_LITTLE; if (sbus_bus_map(iot, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, 0, &ioh) != 0) { printf(": can't map registers\n"); goto free; } /* * PCI config space is mapped at the start of the SBus * register space. We use it to identify the ISP chip. */ id = bus_space_read_4(iot, ioh, PCI_ID_REG); class = bus_space_read_4(iot, ioh, PCI_CLASS_REG); pci_devinfo(id, class, 0, devinfo, sizeof(devinfo)); printf(": %s\n", devinfo); switch (PCI_PRODUCT(id)) { case PCI_PRODUCT_QLOGIC_ISP2200: sc->sc_isp_gen = QLA_GEN_ISP2200; sc->sc_isp_type = QLA_ISP2200; break; case PCI_PRODUCT_QLOGIC_ISP2300: sc->sc_isp_gen = QLA_GEN_ISP23XX; sc->sc_isp_type = QLA_ISP2300; break; case PCI_PRODUCT_QLOGIC_ISP2312: sc->sc_isp_gen = QLA_GEN_ISP23XX; sc->sc_isp_type = QLA_ISP2312; break; default: printf("%s: unsupported ISP chip\n", DEVNAME(sc)); goto unmap; } if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_BIO, 0, qla_intr, sc, sc->sc_dev.dv_xname) == NULL) { printf("%s: can't establish interrupt\n", DEVNAME(sc)); goto unmap; } if (bus_space_subregion(iot, ioh, QLA_SBUS_REG_OFFSET, QLA_SBUS_REG_SIZE, &sc->sc_ioh) != 0) { printf("%s: can't submap registers\n", DEVNAME(sc)); goto unmap; } sc->sc_iot = iot; sc->sc_ios = QLA_SBUS_REG_SIZE; sc->sc_dmat = sa->sa_dmatag; qla_attach(sc); return; unmap: bus_space_unmap(iot, ioh, sa->sa_size); free: free(iot, M_DEVBUF, 0); }