void fbwscons_init(struct sunfb *sf, int flags) { struct rasops_info *ri = &sf->sf_ro; int cols, rows; /* ri_hw and ri_bits must have already been setup by caller */ ri->ri_flg = RI_CENTER | RI_FULLCLEAR | flags; ri->ri_depth = sf->sf_depth; ri->ri_stride = sf->sf_linebytes; ri->ri_width = sf->sf_width; ri->ri_height = sf->sf_height; rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34); cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80); rasops_init(ri, rows, cols); if (sf->sf_depth == 8) { /* * If we are running with an indexed palette, compensate * the swap of black and white through ri_devcmap. */ ri->ri_devcmap[WSCOL_SUN_BLACK] = 0; ri->ri_devcmap[WSCOL_SUN_WHITE] = 0xffffffff; } else if (sf->sf_depth > 8) { /* * If we are running on a direct color frame buffer, * make the ``normal'' white the same as the highlighted * white. */ ri->ri_devcmap[WSCOL_WHITE] = ri->ri_devcmap[WSCOL_WHITE + 8]; } }
void fbwscons_init(struct sunfb *sf, int flags) { struct rasops_info *ri = &sf->sf_ro; int cols, rows; /* ri_hw and ri_bits must have already been setup by caller */ ri->ri_flg = RI_CENTER | RI_FULLCLEAR | flags; ri->ri_depth = sf->sf_depth; ri->ri_stride = sf->sf_linebytes; ri->ri_width = sf->sf_width; ri->ri_height = sf->sf_height; #if defined(SUN4C) || defined(SUN4M) if (CPU_ISSUN4COR4M) { rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34); cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80); } #endif #if defined(SUN4) if (CPU_ISSUN4) { struct eeprom *ep = (struct eeprom *)eeprom_va; if (ep != NULL) { rows = (u_short)ep->eeTtyRows; cols = (u_short)ep->eeTtyCols; /* deal with broken nvram contents... */ if (rows <= 0) rows = 34; if (cols <= 0) cols = 80; } else { rows = 34; cols = 80; } } #endif rasops_init(ri, rows, cols); if (sf->sf_depth == 8) { /* * If we are running with an indexed palette, compensate * the swap of black and white through ri_devcmap. */ ri->ri_devcmap[WSCOL_SUN_BLACK] = 0; ri->ri_devcmap[WSCOL_SUN_WHITE] = 0xffffffff; } else if (sf->sf_depth > 8) { /* * If we are running on a direct color frame buffer, * make the ``normal'' white the same as the hilighted * white. */ ri->ri_devcmap[WSCOL_WHITE] = ri->ri_devcmap[WSCOL_WHITE + 8]; } }
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); }
int gfxp_match(struct device *parent, void *cf, void *aux) { struct pci_attach_args *pa = aux; int node; char *name; node = PCITAG_NODE(pa->pa_tag); name = getpropstring(node, "name"); if (strcmp(name, "TECH-SOURCE,gfxp") == 0 || strcmp(name, "TSI,gfxp") == 0) return (10); return (0); }
int led_match(struct device *parent, void *cf, void *aux) { struct ebus_attach_args *ea = aux; char *str; if (strcmp("env-monitor", ea->ea_name) != 0) return (0); str = getpropstring(ea->ea_node, "compatible"); if (strcmp(str, "epic") == 0) return (1); return (0); }
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 tcxattach(struct device *parent, struct device *self, void *args) { struct tcx_softc *sc = (struct tcx_softc *)self; struct confargs *ca = args; int node, pri; int isconsole = 0; char *nam = NULL; vaddr_t thc_offset; pri = ca->ca_ra.ra_intr[0].int_pri; printf(" pri %d: ", pri); node = ca->ca_ra.ra_node; isconsole = node == fbnode; if (ca->ca_ra.ra_nreg < TCX_NREG) { printf("expected %d registers, got %d\n", TCX_NREG, ca->ca_ra.ra_nreg); return; } nam = getpropstring(node, "model"); if (*nam != '\0') printf("%s, ", nam); /* * Copy the register address spaces needed for mmap operation. */ sc->sc_phys[0] = ca->ca_ra.ra_reg[TCX_REG_DFB8]; sc->sc_phys[1] = ca->ca_ra.ra_reg[TCX_REG_DFB24]; /* * Can't trust the PROM range len here, it is only 4 bytes on the * 8-bit model. Not that it matters much anyway since we map in * pages. */ sc->sc_bt = (volatile struct bt_regs *) mapiodev(&ca->ca_ra.ra_reg[TCX_REG_CMAP], 0, sizeof *sc->sc_bt); /* * For some reason S24 PROM sets up TEC and THC ranges at the * right addresses (701000 and 301000), while 8 bit TCX doesn't * (and uses 70000 and 30000) - be sure to only compensate on 8 bit * models. */ if (((vaddr_t)ca->ca_ra.ra_reg[TCX_REG_THC].rr_paddr & 0x1000) != 0) thc_offset = 0; else thc_offset = 0x1000; sc->sc_thc = (volatile struct tcx_thc *) mapiodev(&ca->ca_ra.ra_reg[TCX_REG_THC], thc_offset, sizeof *sc->sc_thc); /* * Find out frame buffer geometry, so that we know how much * memory to map. */ fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); sc->sc_dfb8 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB8], 0, round_page(sc->sc_sunfb.sf_fbsize)); /* * If the frame buffer advertizes itself as the 8 bit model, or * if the PROM ranges are too small, limit ourselves to 8 bit * operations. * * Further code needing to know which capabilities the frame buffer * has will rely on sc_cplane being non-zero if 24 bit operation * is possible. */ if (!node_has_property(node, "tcx-8-bit") && ca->ca_ra.ra_reg[TCX_REG_RDFB32].rr_len >= sc->sc_sunfb.sf_fbsize * 4) { sc->sc_cplane = (paddr_t)ca->ca_ra.ra_reg[TCX_REG_RDFB32].rr_paddr; } printf("%dx%dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height, sc->sc_cplane == 0 ? 8 : 24); /* * Set up mappings for the acceleration code. This may fail. */ tcx_accel_init(sc, ca); /* reset cursor & frame buffer controls */ tcx_reset(sc, 8); /* enable video */ tcx_burner(sc, 1, 0); sc->sc_sunfb.sf_ro.ri_hw = sc; sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_dfb8; fbwscons_init(&sc->sc_sunfb, isconsole); fbwscons_setcolormap(&sc->sc_sunfb, tcx_setcolor); /* * Now plug accelerated console routines, if possible. */ tcx_accel_plug(sc, ca); sc->sc_ih.ih_fun = tcx_intr; sc->sc_ih.ih_arg = sc; intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, -1); shutdownhook_establish(tcx_prom, sc); } fbwscons_attach(&sc->sc_sunfb, &tcx_accessops, isconsole); }
void cgtwelveattach(struct device *parent, struct device *self, void *args) { struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self; struct confargs *ca = args; int node; int isconsole = 0; char *ps; node = ca->ca_ra.ra_node; printf(": %s", getpropstring(node, "model")); ps = getpropstring(node, "dev_id"); if (*ps != '\0') printf(" (%s)", ps); printf("\n"); isconsole = node == fbnode; sc->sc_phys = ca->ca_ra.ra_reg[0]; /* * Map registers */ sc->sc_dpu = (struct cgtwelve_dpu *)mapiodev(ca->ca_ra.ra_reg, CG12_OFF_DPU, sizeof(struct cgtwelve_dpu)); sc->sc_apu = (struct cgtwelve_apu *)mapiodev(ca->ca_ra.ra_reg, CG12_OFF_APU, sizeof(struct cgtwelve_apu)); sc->sc_ramdac = (struct cgtwelve_dac *)mapiodev(ca->ca_ra.ra_reg, CG12_OFF_DAC, sizeof(struct cgtwelve_dac)); /* * 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, ca->ca_bustype); 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 */ sc->sc_overlay = mapiodev(ca->ca_ra.ra_reg, sc->sc_highres ? CG12_OFF_OVERLAY0_HR : CG12_OFF_OVERLAY0, round_page(sc->sc_highres ? CG12_SIZE_OVERLAY_HR : CG12_SIZE_OVERLAY)); sc->sc_inten = mapiodev(ca->ca_ra.ra_reg, sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN, round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR : CG12_SIZE_COLOR24)); /* 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, isconsole ? 0 : RI_CLEAR); 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); }
/* * 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); }
void cgthreeattach(struct device *parent, struct device *self, void *aux) { struct cgthree_softc *sc = (struct cgthree_softc *)self; struct sbus_attach_args *sa = aux; int node, console; const char *nam; node = sa->sa_node; sc->sc_bustag = sa->sa_bustag; sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset); fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); if (sa->sa_nreg != 1) { printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); goto fail; } /* * Map just CTRL and video RAM. */ if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset + CGTHREE_CTRL_OFFSET, CGTHREE_CTRL_SIZE, 0, 0, &sc->sc_ctrl_regs) != 0) { printf(": cannot map ctrl registers\n"); goto fail_ctrl; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset + CGTHREE_VID_OFFSET, sc->sc_sunfb.sf_fbsize, BUS_SPACE_MAP_LINEAR, 0, &sc->sc_vid_regs) != 0) { printf(": cannot map vid registers\n"); goto fail_vid; } nam = getpropstring(node, "model"); if (*nam == '\0') nam = sa->sa_name; printf(": %s", nam); console = cgthree_is_console(node); cgthree_reset(sc); cgthree_burner(sc, 1, 0); sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bustag, sc->sc_vid_regs); sc->sc_sunfb.sf_ro.ri_hw = sc; printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); /* * If the framebuffer width is under 1024x768, which is the case for * some clones on laptops, as well as with the VS10-EK, switch from * the PROM font to the more adequate 8x16 font here. * However, we need to adjust two things in this case: * - the display row should be overrided from the current PROM metrics, * to prevent us from overwriting the last few lines of text. * - if the 80x34 screen would make a large margin appear around it, * choose to clear the screen rather than keeping old prom output in * the margins. * XXX there should be a rasops "clear margins" feature */ fbwscons_init(&sc->sc_sunfb, console && (sc->sc_sunfb.sf_width >= 1024) ? 0 : RI_CLEAR); fbwscons_setcolormap(&sc->sc_sunfb, cgthree_setcolor); if (console) { fbwscons_console_init(&sc->sc_sunfb, sc->sc_sunfb.sf_width >= 1024 ? -1 : 0); } fbwscons_attach(&sc->sc_sunfb, &cgthree_accessops, console); return; fail_vid: bus_space_unmap(sa->sa_bustag, sc->sc_ctrl_regs, CGTHREE_CTRL_SIZE); fail_ctrl: fail: ; }
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); }
void gfxp_attach(struct device *parent, struct device *self, void *aux) { struct gfxp_softc *sc = (struct gfxp_softc *)self; struct pci_attach_args *pa = aux; struct rasops_info *ri; int node, console, flags; char *model; sc->sc_pcitag = pa->pa_tag; node = PCITAG_NODE(pa->pa_tag); console = gfxp_is_console(node); printf("\n"); model = getpropstring(node, "model"); printf("%s: %s", self->dv_xname, model); if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PM2_PCI_MEM_LE, PCI_MAPREG_TYPE_MEM, &sc->sc_membase_le, &sc->sc_memsize_le, NULL)) sc->sc_memsize_le = 0; if (pci_mapreg_map(pa, PM2_PCI_MEM_BE, PCI_MAPREG_TYPE_MEM, BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, &sc->sc_membase_be, &sc->sc_memsize_be, 0)) { printf("\n%s: can't map video memory\n", self->dv_xname); return; } if (pci_mapreg_map(pa, PM2_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase, &sc->sc_mmiosize, 0)) { bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize_be); printf("\n%s: can't map mmio\n", self->dv_xname); return; } fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); ri = &sc->sc_sunfb.sf_ro; ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh); ri->ri_hw = sc; flags = RI_BSWAP; if (sc->sc_sunfb.sf_depth == 32) { ri->ri_rnum = 8; ri->ri_rpos = 16; ri->ri_gnum = 8; ri->ri_gpos = 8; ri->ri_bnum = 8; ri->ri_bpos = 0; flags &= ~RI_BSWAP; } fbwscons_init(&sc->sc_sunfb, flags, console); fbwscons_setcolormap(&sc->sc_sunfb, gfxp_setcolor); sc->sc_mode = WSDISPLAYIO_MODE_EMUL; gfxp_init(sc); ri->ri_ops.copyrows = gfxp_copyrows; ri->ri_ops.copycols = gfxp_copycols; ri->ri_ops.eraserows = gfxp_eraserows; ri->ri_ops.erasecols = gfxp_erasecols; if (console) fbwscons_console_init(&sc->sc_sunfb, -1); fbwscons_attach(&sc->sc_sunfb, &gfxp_accessops, console); }
void agtenattach(struct device *parent, struct device *self, void *args) { struct agten_softc *sc = (struct agten_softc *)self; struct confargs *ca = args; struct wsemuldisplaydev_attach_args waa; int node, isconsole; char *nam; sc->sc_sunfb.sf_flags = self->dv_cfdata->cf_flags; node = ca->ca_ra.ra_node; nam = getpropstring(node, "model"); printf(": model %s", nam); isconsole = node == fbnode; sc->sc_phys = ca->ca_ra.ra_reg[0]; /* * Map the various beasts of this card we are interested in. */ sc->sc_physoffset = (off_t)getpropint(node, "i128_fb_physaddr", 0x8000000); sc->sc_i128_fb = mapiodev(ca->ca_ra.ra_reg, sc->sc_physoffset, getpropint(node, "i128_fb_size", 0x400000)); sc->sc_dac = mapiodev(ca->ca_ra.ra_reg, getpropint(node, "p9100_reg_physaddr", 0x10a0000) + 0x200, 0x800 - 0x200); /* * 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, isconsole); fbwscons_setcolormap(&sc->sc_sunfb, agten_setcolor); agten_stdscreen.capabilities = sc->sc_sunfb.sf_ro.ri_caps; agten_stdscreen.nrows = sc->sc_sunfb.sf_ro.ri_rows; agten_stdscreen.ncols = sc->sc_sunfb.sf_ro.ri_cols; agten_stdscreen.textops = &sc->sc_sunfb.sf_ro.ri_ops; if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, &agten_stdscreen, -1, NULL); } sbus_establish(&sc->sc_sd, &sc->sc_sunfb.sf_dev); waa.console = isconsole; waa.scrdata = &agten_screenlist; waa.accessops = &agten_accessops; waa.accesscookie = sc; config_found(self, &waa, wsemuldisplaydevprint); }
void bwtwoattach(struct device *parent, struct device *self, void *args) { struct bwtwo_softc *sc = (struct bwtwo_softc *)self; struct confargs *ca = args; int node = ca->ca_ra.ra_node; int isconsole = 0; int sbus = 1; char *nam; printf(": "); /* * Map the control register. */ #if defined(SUN4) if (CPU_ISSUN4 && ca->ca_bustype == BUS_OBIO && fb_pfour_id(ca->ca_ra.ra_vaddr) != PFOUR_NOTPFOUR) { SET(sc->sc_sunfb.sf_flags, FB_PFOUR); sc->sc_sunfb.sf_pfour = (volatile u_int32_t *) mapiodev(ca->ca_ra.ra_reg, 0, sizeof(u_int32_t)); } else #endif { sc->sc_reg = (volatile struct fbcontrol *) mapiodev(ca->ca_ra.ra_reg, BWREG_REG, sizeof(struct fbcontrol)); } /* Set up default pixel offset. May be changed below. */ sc->sc_pixeloffset = BWREG_MEM; switch (ca->ca_bustype) { case BUS_OBIO: if (CPU_ISSUN4M) /* 4m has framebuffer on obio */ goto obp_name; sbus = node = 0; #if defined(SUN4) if (ISSET(sc->sc_sunfb.sf_flags, FB_PFOUR)) { nam = "p4"; sc->sc_pixeloffset = PFOUR_BW_OFF; } else #endif nam = NULL; break; case BUS_VME32: case BUS_VME16: sbus = node = 0; nam = NULL; break; case BUS_SBUS: obp_name: #if defined(SUN4C) || defined(SUN4M) nam = getpropstring(node, "model"); #endif break; } if (nam != NULL && *nam != '\0') printf("%s, ", nam); #if defined(SUN4) if (CPU_ISSUN4) { struct eeprom *eep = (struct eeprom *)eeprom_va; int constype = ISSET(sc->sc_sunfb.sf_flags, FB_PFOUR) ? EE_CONS_P4OPT : EE_CONS_BW; /* * Assume this is the console if there's no eeprom info * to be found. */ if (eep == NULL || eep->eeConsole == constype) isconsole = 1; else /* * On sun4 systems without on-board framebuffers (such as * the 4/3xx models), the PROM will accept the EE_CONS_BW * setting although the framebuffer is a P4. * Accept this setting as well. */ if (eep->eeConsole == EE_CONS_BW) isconsole = 1; } #endif if (CPU_ISSUN4COR4M) isconsole = node == fbnode; sc->sc_phys = ca->ca_ra.ra_reg[0]; sc->sc_bustype = ca->ca_bustype; /* enable video */ bwtwo_burner(sc, 1, 0); fb_setsize(&sc->sc_sunfb, 1, 1152, 900, node, ca->ca_bustype); printf("%dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg, sc->sc_pixeloffset, round_page(sc->sc_sunfb.sf_fbsize)); sc->sc_sunfb.sf_ro.ri_hw = sc; fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, -1); } fbwscons_attach(&sc->sc_sunfb, &bwtwo_accessops, isconsole); }
void cgsixattach(struct device *parent, struct device *self, void *aux) { struct cgsix_softc *sc = (struct cgsix_softc *)self; struct sbus_attach_args *sa = aux; int node, console; u_int32_t fhc, rev; const char *nam; node = sa->sa_node; sc->sc_bustag = sa->sa_bustag; sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset); if (sa->sa_nreg != 1) { printf(": expected %d registers, got %d\n", 1, sa->sa_nreg); goto fail; } fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); /* * Map just BT, FHC, FBC, THC, and video RAM. */ if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset + CGSIX_BT_OFFSET, CGSIX_BT_SIZE, 0, 0, &sc->sc_bt_regs) != 0) { printf(": cannot map bt registers\n"); goto fail_bt; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset + CGSIX_FHC_OFFSET, CGSIX_FHC_SIZE, 0, 0, &sc->sc_fhc_regs) != 0) { printf(": cannot map fhc registers\n"); goto fail_fhc; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset + CGSIX_THC_OFFSET, CGSIX_THC_SIZE, 0, 0, &sc->sc_thc_regs) != 0) { printf(": cannot map thc registers\n"); goto fail_thc; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset + CGSIX_VID_OFFSET, sc->sc_sunfb.sf_fbsize, BUS_SPACE_MAP_LINEAR, 0, &sc->sc_vid_regs) != 0) { printf(": cannot map vid registers\n"); goto fail_vid; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset + CGSIX_TEC_OFFSET, CGSIX_TEC_SIZE, 0, 0, &sc->sc_tec_regs) != 0) { printf(": cannot map tec registers\n"); goto fail_tec; } if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, sa->sa_reg[0].sbr_offset + CGSIX_FBC_OFFSET, CGSIX_FBC_SIZE, 0, 0, &sc->sc_fbc_regs) != 0) { printf(": cannot map fbc registers\n"); goto fail_fbc; } if ((sc->sc_ih = bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0, cgsix_intr, sc, self->dv_xname)) == NULL) { printf(": couldn't establish interrupt, pri %d\n%s", INTLEV(sa->sa_pri), self->dv_xname); } /* if prom didn't initialize us, do it the hard way */ if (OF_getproplen(node, "width") != sizeof(u_int32_t)) cgsix_hardreset(sc); nam = getpropstring(node, "model"); if (*nam == '\0') nam = sa->sa_name; printf(": %s", nam); console = cgsix_is_console(node); fhc = FHC_READ(sc); rev = (fhc & FHC_REV_MASK) >> FHC_REV_SHIFT; cgsix_reset(sc, rev); cgsix_burner(sc, 1, 0); sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bustag, sc->sc_vid_regs); sc->sc_sunfb.sf_ro.ri_hw = sc; printf(", %dx%d, rev %d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height, rev); fbwscons_init(&sc->sc_sunfb, 0, console); fbwscons_setcolormap(&sc->sc_sunfb, cgsix_setcolor); /* * Old rev. cg6 cards do not like the current acceleration code. * * Some hints from Sun point out at timing and cache problems, which * will be investigated later. */ if (rev < 5) sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags |= CG6_CFFLAG_NOACCEL; if ((sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags & CG6_CFFLAG_NOACCEL) == 0) { sc->sc_sunfb.sf_ro.ri_ops.copyrows = cgsix_ras_copyrows; sc->sc_sunfb.sf_ro.ri_ops.copycols = cgsix_ras_copycols; sc->sc_sunfb.sf_ro.ri_ops.eraserows = cgsix_ras_eraserows; sc->sc_sunfb.sf_ro.ri_ops.erasecols = cgsix_ras_erasecols; sc->sc_sunfb.sf_ro.ri_do_cursor = cgsix_ras_do_cursor; cgsix_ras_init(sc); } if (console) fbwscons_console_init(&sc->sc_sunfb, -1); fbwscons_attach(&sc->sc_sunfb, &cgsix_accessops, console); return; fail_fbc: bus_space_unmap(sa->sa_bustag, sc->sc_tec_regs, CGSIX_TEC_SIZE); fail_tec: bus_space_unmap(sa->sa_bustag, sc->sc_vid_regs, sc->sc_sunfb.sf_fbsize); fail_vid: bus_space_unmap(sa->sa_bustag, sc->sc_thc_regs, CGSIX_THC_SIZE); fail_thc: bus_space_unmap(sa->sa_bustag, sc->sc_fhc_regs, CGSIX_FHC_SIZE); fail_fhc: bus_space_unmap(sa->sa_bustag, sc->sc_bt_regs, CGSIX_BT_SIZE); fail_bt: fail: return; }
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 fhc_attach(struct fhc_softc *sc) { int node0, node; u_int32_t ctrl; printf(" board %d: %s\n", sc->sc_board, getpropstring(sc->sc_node, "board-model")); sc->sc_cbt = fhc_alloc_bus_tag(sc); sc->sc_ign = sc->sc_board << 1; bus_space_write_4(sc->sc_bt, sc->sc_ireg, FHC_I_IGN, sc->sc_ign); sc->sc_ign = bus_space_read_4(sc->sc_bt, sc->sc_ireg, FHC_I_IGN); ctrl = bus_space_read_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL); if (!sc->sc_is_central) ctrl |= FHC_P_CTRL_IXIST; ctrl &= ~(FHC_P_CTRL_AOFF | FHC_P_CTRL_BOFF | FHC_P_CTRL_SLINE); bus_space_write_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL, ctrl); bus_space_read_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL); /* clear interrupts */ bus_space_write_4(sc->sc_bt, sc->sc_freg, FHC_F_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_freg, FHC_F_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_sreg, FHC_S_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_sreg, FHC_S_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_ureg, FHC_U_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_ureg, FHC_U_ICLR); bus_space_write_4(sc->sc_bt, sc->sc_treg, FHC_T_ICLR, 0); bus_space_read_4(sc->sc_bt, sc->sc_treg, FHC_T_ICLR); getprop(sc->sc_node, "ranges", sizeof(struct fhc_range), &sc->sc_nrange, (void **)&sc->sc_range); node0 = firstchild(sc->sc_node); for (node = node0; node; node = nextsibling(node)) { struct fhc_attach_args fa; bzero(&fa, sizeof(fa)); fa.fa_node = node; fa.fa_bustag = sc->sc_cbt; if (fhc_get_string(fa.fa_node, "name", &fa.fa_name)) { printf("can't fetch name for node 0x%x\n", node); continue; } getprop(node, "reg", sizeof(struct fhc_reg), &fa.fa_nreg, (void **)&fa.fa_reg); getprop(node, "interrupts", sizeof(int), &fa.fa_nintr, (void **)&fa.fa_intr); getprop(node, "address", sizeof(*fa.fa_promvaddrs), &fa.fa_npromvaddrs, (void **)&fa.fa_promvaddrs); (void)config_found(&sc->sc_dv, (void *)&fa, fhc_print); if (fa.fa_name != NULL) free(fa.fa_name, M_DEVBUF); if (fa.fa_reg != NULL) free(fa.fa_reg, M_DEVBUF); if (fa.fa_nintr != NULL) free(fa.fa_intr, M_DEVBUF); if (fa.fa_promvaddrs != NULL) free(fa.fa_promvaddrs, M_DEVBUF); } sc->sc_blink.bl_func = fhc_led_blink; sc->sc_blink.bl_arg = sc; blink_led_register(&sc->sc_blink); }
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 fbwscons_init(struct sunfb *sf, int flags, int isconsole) { struct rasops_info *ri = &sf->sf_ro; int cols, rows, fw, fh, wt, wl; /* ri_hw and ri_bits must have already been setup by caller */ ri->ri_flg = RI_FULLCLEAR | flags; ri->ri_depth = sf->sf_depth; ri->ri_stride = sf->sf_linebytes; ri->ri_width = sf->sf_width; ri->ri_height = sf->sf_height; rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34); cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80); /* * If the framebuffer width is under 960 pixels, rasops will * switch from the 12x22 font to the more adequate 8x16 font * here. * If we are the console device, we need to adjust two things: * - the display row should be overrided from the current PROM * metrics, since it will not match the PROM reality anymore. * - the screen needs to be cleared. * * However, to accommodate laptops with specific small fonts, * it is necessary to compare the resolution with the actual * font metrics. */ if (isconsole) { if (fb_get_console_metrics(&fw, &fh, &wt, &wl) != 0) { /* * Assume a 12x22 prom font and a centered * 80x34 console window. */ fw = 12; fh = 22; wt = wl = 0; } else { /* * Make sure window-top and window-left * values are consistent with the font metrics. */ if (wt <= 0 || wt > sf->sf_height - rows * fh || wl <= 0 || wl > sf->sf_width - cols * fw) wt = wl = 0; } if (wt == 0 /* || wl == 0 */) { ri->ri_flg |= RI_CENTER; /* * Since the console window might not be * centered (e.g. on a 1280x1024 vigra * VS-12 frame buffer), have rasops * clear the margins even if the screen is * not cleared. */ ri->ri_flg |= RI_CLEARMARGINS; } if (ri->ri_wsfcookie != 0) { /* driver handles font issues. do nothing. */ } else { /* * If the PROM uses a different font than the * one we are expecting it to use, or if the * display is shorter than 960 pixels wide, * we'll force a screen clear. */ if (fw != 12 || sf->sf_width < 12 * 80) ri->ri_flg |= RI_CLEAR | RI_CENTER; } } else { ri->ri_flg |= RI_CLEAR | RI_CENTER; } /* ifb(4) doesn't set ri_bits at the moment */ if (ri->ri_bits == NULL) ri->ri_flg &= ~(RI_CLEAR | RI_CLEARMARGINS); rasops_init(ri, rows, cols); /* * If this is the console display and there is no font change, * adjust our terminal window to the position of the PROM * window - in case it is not exactly centered. */ if ((ri->ri_flg & RI_CENTER) == 0) { /* code above made sure wt and wl are initialized */ ri->ri_bits += wt * ri->ri_stride; if (ri->ri_depth >= 8) /* for 15bpp to compute ok */ ri->ri_bits += wl * ri->ri_pelbytes; else ri->ri_bits += (wl * ri->ri_depth) >> 3; ri->ri_xorigin = wl; ri->ri_yorigin = wt; }
void cgthreeattach(struct device *parent, struct device *self, void *args) { struct cgthree_softc *sc = (struct cgthree_softc *)self; struct confargs *ca = args; int node, pri, isrdi = 0, i; volatile struct bt_regs *bt; int isconsole; char *nam; pri = ca->ca_ra.ra_intr[0].int_pri; printf(" pri %d: ", pri); node = ca->ca_ra.ra_node; if (strcmp(ca->ca_ra.ra_name, "cgRDI") == 0) { isrdi = 1; nam = "cgRDI"; } else nam = getpropstring(node, "model"); if (nam != NULL && *nam != '\0') printf("%s, ", nam); isconsole = node == fbnode; sc->sc_fbc = (volatile struct fbcontrol *) mapiodev(ca->ca_ra.ra_reg, CG3REG_REG, sizeof(struct fbcontrol)); /* Transfer video magic to board, if it's not running */ if (isrdi == 0 && (sc->sc_fbc->fbc_ctrl & FBC_TIMING) == 0) for (i = 0; i < sizeof(cg3_videoctrl)/sizeof(cg3_videoctrl[0]); i++) { volatile struct fbcontrol *fbc = sc->sc_fbc; if (cg3_videoctrl[i].sense == 0xff || (fbc->fbc_status & FBS_MSENSE) == cg3_videoctrl[i].sense) { int j; #ifdef DEBUG printf(" (setting video ctrl)"); #endif for (j = 0; j < 12; j++) fbc->fbc_vcontrol[j] = cg3_videoctrl[i].vctrl[j]; fbc->fbc_ctrl |= FBC_TIMING; break; } } sc->sc_phys = ca->ca_ra.ra_reg[0]; sc->sc_ih.ih_fun = cgthree_intr; sc->sc_ih.ih_arg = sc; intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname); /* enable video */ cgthree_burner(sc, 1, 0); bt = &sc->sc_fbc->fbc_dac; BT_INIT(bt, 0); fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg, CG3REG_MEM, round_page(sc->sc_sunfb.sf_fbsize)); sc->sc_sunfb.sf_ro.ri_hw = sc; printf("%dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); /* * If the framebuffer width is under 1024x768, which is the case for * some clones on laptops, as well as with the VS10-EK, switch from * the PROM font to the more adequate 8x16 font here. * However, we need to adjust two things in this case: * - the display row should be overrided from the current PROM metrics, * to prevent us from overwriting the last few lines of text. * - if the 80x34 screen would make a large margin appear around it, * choose to clear the screen rather than keeping old prom output in * the margins. * XXX there should be a rasops "clear margins" feature */ fbwscons_init(&sc->sc_sunfb, isconsole && (sc->sc_sunfb.sf_width >= 1024) ? 0 : RI_CLEAR); fbwscons_setcolormap(&sc->sc_sunfb, cgthree_setcolor); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, sc->sc_sunfb.sf_width >= 1024 ? -1 : 0); } fbwscons_attach(&sc->sc_sunfb, &cgthree_accessops, isconsole); }
void presto_attach(struct device *parent, struct device *self, void *args) { struct presto_softc *sc = (struct presto_softc *)self; struct confargs *ca = args; char *model, *submodel; u_int8_t status; /* Get card parameters */ model = getpropstring(ca->ca_ra.ra_node, "model"); if (*model == '\0') submodel = "fictitious"; else { submodel = memchr(model, ',', strlen(model)); if (submodel != NULL) submodel++; else submodel = model; } strncpy(sc->sc_model, submodel, 16); sc->sc_memsize = ca->ca_ra.ra_len; printf(": %s\n%s: %d MB NVRAM, ", model, sc->sc_dev.dv_xname, sc->sc_memsize >> 20); /* Map memory */ sc->sc_mem = (void *)mapiodev(ca->ca_ra.ra_reg, 0, sc->sc_memsize); /* * Clear the ``disconnect battery'' bit. */ *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS) = 0x00; /* * Clear the ``unflushed data'' status. This way, if the card is * reused under SunOS, the system will not try to flush whatever * data the user put in the nvram... */ *(u_int8_t *)(sc->sc_mem + PSERVE_DATASTATUS) = 0x00; /* * Decode battery status */ status = *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS); printf("battery status %x ", status); if (ISSET(status, PSBAT_FAULT)) { printf("(non-working)"); } else if (ISSET(status, PSBAT_CONNECTED)) { if (ISSET(status, PSBAT_CHARGING)) printf("(charging)"); else printf("(ok)"); } else printf("(disabled)"); printf("\n"); #ifdef DEBUG printf("%s: status codes %02.2x, %02.2x, %02.2x, %02.2x\n", sc->sc_dev.dv_xname, *(u_int8_t *)(sc->sc_mem + 0x03), *(u_int8_t *)(sc->sc_mem + 0x07), *(u_int8_t *)(sc->sc_mem + 0x0b), *(u_int8_t *)(sc->sc_mem + 0x0f)); #endif sc->sc_dk.dk_driver = &presto_dk; sc->sc_dk.dk_name = sc->sc_dev.dv_xname; disk_attach(&sc->sc_dk); /* read the disk label immediately */ presto_getdisklabel(sc); }
/* * 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); }
/* * Attach and initialize a vigra display, as well as a child wsdisplay. */ void vigraattach(struct device *parent, struct device *self, void *args) { struct vigra_softc *sc = (struct vigra_softc *)self; struct sbus_attach_args *sa = args; bus_space_tag_t bt; bus_space_handle_t bh; int node, row, isconsole = 0; char *nam; bt = sa->sa_bustag; node = sa->sa_node; nam = getpropstring(node, "model"); if (*nam == '\0') nam = (char *)sa->sa_name; printf(": %s", nam); isconsole = node == fbnode; if (sa->sa_nreg < VIGRA_NREG) { printf("\n%s: expected %d registers, got %d", self->dv_xname, VIGRA_NREG, sa->sa_nreg); return; } /* * Check whether we are using an G300 or an G335 chip. * The VS10 and VS12 use the G300, while the VS11 uses a G335. */ sc->sc_g300 = strncmp(nam, "VIGRA,vs11", strlen("VIGRA,vs11")); sc->sc_bustag = bt; if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_CSR].sbr_slot, sa->sa_reg[VIGRA_REG_CSR].sbr_offset, sa->sa_reg[VIGRA_REG_CSR].sbr_size, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: can't map control registers\n", self->dv_xname); return; } sc->sc_regs = bus_space_vaddr(bt, bh); if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_RAMDAC].sbr_slot, sa->sa_reg[VIGRA_REG_RAMDAC].sbr_offset, sa->sa_reg[VIGRA_REG_RAMDAC].sbr_size, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: can't map ramdac registers\n", self->dv_xname); return; } sc->sc_ramdac = bus_space_vaddr(bt, bh); /* enable video */ vigra_burner(sc, 1, 0); fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_VRAM].sbr_slot, sa->sa_reg[VIGRA_REG_VRAM].sbr_offset, round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { printf("\n%s: can'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; sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[VIGRA_REG_VRAM].sbr_slot, sa->sa_reg[VIGRA_REG_VRAM].sbr_offset); printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); if ((sc->sc_ih = bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0, vigra_intr, sc, self->dv_xname)) == NULL) { printf("%s: couldn't establish interrupt, pri %d\n", self->dv_xname, INTLEV(sa->sa_pri)); } /* * If the framebuffer width is under 1024x768, we will switch from the * PROM font to the more adequate 8x16 font here. * However, we need to adjust two things in this case: * - the display row should be overrided from the current PROM metrics, * to prevent us from overwriting the last few lines of text. * - if the 80x34 screen would make a large margin appear around it, * choose to clear the screen rather than keeping old prom output in * the margins. * XXX there should be a rasops "clear margins" feature * * Also, in 1280x1024 resolution, the PROM display is not centered * vertically (why? no other frame buffer does this in such a mode!), * so be lazy and clear the screen here too anyways... */ fbwscons_init(&sc->sc_sunfb, isconsole && (sc->sc_sunfb.sf_width != 800 && sc->sc_sunfb.sf_width != 1280) ? 0 : RI_CLEAR); fbwscons_setcolormap(&sc->sc_sunfb, vigra_setcolor); if (isconsole) { switch (sc->sc_sunfb.sf_width) { case 640: row = sc->sc_sunfb.sf_ro.ri_rows - 1; break; case 800: case 1280: row = 0; /* screen has been cleared above */ break; default: row = -1; break; } fbwscons_console_init(&sc->sc_sunfb, row); } fbwscons_attach(&sc->sc_sunfb, &vigra_accessops, isconsole); }