void gfb_attach(struct device *parent, struct device *self, void *aux) { struct gfb_softc *sc = (struct gfb_softc *)self; struct mainbus_attach_args *ma = aux; extern int fbnode; sc->sc_bt = ma->ma_bustag; printf("\n"); if (bus_space_map(ma->ma_bustag, ma->ma_reg[6].ur_paddr, ma->ma_reg[6].ur_len, BUS_SPACE_MAP_LINEAR, &sc->sc_pixel_h)) return; sc->sc_console = (fbnode == ma->ma_node); sc->sc_node = ma->ma_node; fb_setsize(&sc->sc_sunfb, 32, 1152, 900, sc->sc_node, 0); /* linesize has a fixed value, compensate */ sc->sc_sunfb.sf_linebytes = 16384; sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height * 16384; sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bt, sc->sc_pixel_h); sc->sc_sunfb.sf_ro.ri_hw = sc; fbwscons_init(&sc->sc_sunfb, 0, sc->sc_console); if (sc->sc_console) fbwscons_console_init(&sc->sc_sunfb, -1); fbwscons_attach(&sc->sc_sunfb, &gfb_accessops, sc->sc_console); return; }
void cgeightattach(struct device *parent, struct device *self, void *args) { struct cgeight_softc *sc = (struct cgeight_softc *)self; struct confargs *ca = args; int node = 0; volatile struct bt_regs *bt; int isconsole = 0; /* Map the pfour register. */ 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)); if (cputyp == CPU_SUN4) { struct eeprom *eep = (struct eeprom *)eeprom_va; /* * Assume this is the console if there's no eeprom info * to be found. */ if (eep == NULL || eep->ee_diag.eed_console == EED_CONS_P4) isconsole = 1; } /* Map the Brooktree. */ sc->sc_fbc = (volatile struct fbcontrol *) mapiodev(ca->ca_ra.ra_reg, PFOUR_COLOR_OFF_CMAP, sizeof(struct fbcontrol)); sc->sc_phys = ca->ca_ra.ra_reg[0]; /* enable video */ fb_pfour_burner(sc, 1, 0); bt = &sc->sc_fbc->fbc_dac; BT_INIT(bt, 0); fb_setsize(&sc->sc_sunfb, 1, 1152, 900, node, ca->ca_bustype); sc->sc_sunfb.sf_ro.ri_hw = sc; /* * Map the overlay and overlay enable planes. */ sc->sc_enable = (volatile u_char *)mapiodev(ca->ca_ra.ra_reg, PFOUR_COLOR_OFF_ENABLE, round_page(sc->sc_sunfb.sf_fbsize)); sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg, PFOUR_COLOR_OFF_OVERLAY, round_page(sc->sc_sunfb.sf_fbsize)); cgeight_reset(sc, WSDISPLAYIO_MODE_EMUL); printf(": p4, %dx%d", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); fbwscons_init(&sc->sc_sunfb, isconsole); if (isconsole) fbwscons_console_init(&sc->sc_sunfb, -1); fbwscons_attach(&sc->sc_sunfb, &cgeight_accessops, isconsole); }
void cgtwoattach(struct device *parent, struct device *self, void *args) { struct cgtwo_softc *sc = (struct cgtwo_softc *)self; struct confargs *ca = args; int node = 0; int isconsole = 0; if (CPU_ISSUN4) { struct eeprom *eep = (struct eeprom *)eeprom_va; /* * Assume this is the console if there's no eeprom info * to be found. */ if (eep == NULL || eep->eeConsole == EE_CONS_COLOR) isconsole = 1; } /* * When the ROM has mapped in a cgtwo display, the address * maps only the video RAM, so in any case we have to map the * registers ourselves. */ sc->sc_phys = ca->ca_ra.ra_reg[0]; /* Apparently, the pixels are 32-bit data space */ sc->sc_phys.rr_iospace = PMAP_VME32; sc->sc_reg = (volatile struct cg2statusreg *) mapiodev(ca->ca_ra.ra_reg, CG2_ROPMEM_OFF + offsetof(struct cg2fb, status.reg), sizeof(struct cg2statusreg)); sc->sc_ppmask = (volatile u_short *) mapiodev(ca->ca_ra.ra_reg, CG2_ROPMEM_OFF + offsetof(struct cg2fb, ppmask.reg), sizeof(u_short)); sc->sc_cmap = (volatile u_short *) mapiodev(ca->ca_ra.ra_reg, CG2_ROPMEM_OFF + offsetof(struct cg2fb, redmap), 3 * CG2_CMSIZE * sizeof(u_short)); /* enable video */ *sc->sc_ppmask = 0xffff; /* enable all color planes... */ cgtwo_burner(sc, 1, 0); /* ... and video signals */ fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); sc->sc_sunfb.sf_ro.ri_bits = mapiodev(&sc->sc_phys, CG2_PIXMAP_OFF, round_page(sc->sc_sunfb.sf_fbsize)); sc->sc_sunfb.sf_ro.ri_hw = sc; fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR); fbwscons_setcolormap(&sc->sc_sunfb, cgtwo_setcolor); printf(": %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, -1); } fbwscons_attach(&sc->sc_sunfb, &cgtwo_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 cgfourattach(struct device *parent, struct device *self, void *args) { struct cgfour_softc *sc = (struct cgfour_softc *)self; struct confargs *ca = args; int node = 0; volatile struct bt_regs *bt; int isconsole = 0; printf(": p4"); /* Map the pfour register. */ 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)); if (cputyp == CPU_SUN4) { struct eeprom *eep = (struct eeprom *)eeprom_va; /* * Assume this is the console if there's no eeprom info * to be found. */ if (eep == NULL || eep->eeConsole == EE_CONS_P4OPT) isconsole = 1; } /* * When the ROM has mapped in a cgfour 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. */ sc->sc_phys = ca->ca_ra.ra_reg[0]; /* enable video */ fb_pfour_burner(sc, 1, 0); bt = &sc->sc_fbc->fbc_dac; BT_INIT(bt, 24); /* * XXX should initialize the enable plane, instead of expecting the * PROM to do so for us */ fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); /* * XXX this only maps the color plane, not the overlay or the enable * planes */ sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg, PFOUR_COLOR_OFF_COLOR, round_page(sc->sc_sunfb.sf_fbsize)); sc->sc_sunfb.sf_ro.ri_hw = sc; fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR); fbwscons_setcolormap(&sc->sc_sunfb, cgfour_setcolor); printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, -1); } fbwscons_attach(&sc->sc_sunfb, &cgfour_accessops, isconsole); }
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 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 p9000attach(struct device *parent, struct device *self, void *args) { struct p9000_softc *sc = (struct p9000_softc *)self; struct confargs *ca = args; int node, pri, row, isconsole, scr; struct device *btdev; extern struct cfdriver btcham_cd; pri = ca->ca_ra.ra_intr[0].int_pri; printf(" pri %d", pri); #ifdef DIAGNOSTIC if (ca->ca_ra.ra_nreg < P9000_NREG) { printf(": expected %d registers, got only %d\n", P9000_NREG, ca->ca_ra.ra_nreg); return; } #endif /* * Find the RAMDAC device. It should have attached before, since it * attaches at obio. If, for some reason, it did not, it's not worth * going any further. * * We rely upon the PROM to properly initialize the RAMDAC in a safe * mode. */ btdev = btcham_cd.cd_ndevs != 0 ? btcham_cd.cd_devs[0] : NULL; if (btdev != NULL) sc->sc_ramdac = ((struct bt445_softc *)btdev)->sc_regs; if (sc->sc_ramdac == NULL) { printf(": bt445 did not attach previously\n"); return; } sc->sc_phys = ca->ca_ra.ra_reg[P9000_REG_VRAM]; sc->sc_ctl = mapiodev(&(ca->ca_ra.ra_reg[P9000_REG_CTL]), 0, ca->ca_ra.ra_reg[0].rr_len); sc->sc_cmd = mapiodev(&(ca->ca_ra.ra_reg[P9000_REG_CMD]), 0, ca->ca_ra.ra_reg[1].rr_len); node = ca->ca_ra.ra_node; isconsole = node == fbnode; fb_setsize(&sc->sc_sunfb, 8, 640, 480, node, ca->ca_bustype); sc->sc_sunfb.sf_ro.ri_bits = mapiodev(&sc->sc_phys, 0, round_page(sc->sc_sunfb.sf_fbsize)); sc->sc_sunfb.sf_ro.ri_hw = sc; P9000_SELECT_SCR(sc); scr = P9000_READ_CTL(sc, P9000_SYSTEM_CONFIG); printf(": rev %x, %dx%d\n", scr & SCR_ID_MASK, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); /* Disable frame buffer interrupts */ P9000_SELECT_SCR(sc); P9000_WRITE_CTL(sc, P9000_INTERRUPT_ENABLE, IER_MASTER_ENABLE | 0); sc->sc_ih.ih_fun = p9000_intr; sc->sc_ih.ih_arg = sc; intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname); /* * 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 */ fbwscons_init(&sc->sc_sunfb, isconsole && (sc->sc_sunfb.sf_width >= 1024) ? 0 : RI_CLEAR); fbwscons_setcolormap(&sc->sc_sunfb, p9000_setcolor); /* * Plug-in accelerated console operations. */ if (sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags != 0) p9000_ras_init(sc); /* enable video */ p9000_burner(sc, 1, 0); if (isconsole) { if (sc->sc_sunfb.sf_width < 1024) row = 0; /* screen has been cleared above */ else row = -1; fbwscons_console_init(&sc->sc_sunfb, row); } fbwscons_attach(&sc->sc_sunfb, &p9000_accessops, isconsole); }
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; }
/* * Attach a display. */ void p9100attach(struct device *parent, struct device *self, void *args) { struct p9100_softc *sc = (struct p9100_softc *)self; struct rasops_info *ri = &sc->sc_sunfb.sf_ro; struct confargs *ca = args; struct romaux *ra = &ca->ca_ra; int node, pri, scr, force_reset; int isconsole, fontswitch, clear = 0; pri = ca->ca_ra.ra_intr[0].int_pri; printf(" pri %d", pri); #ifdef DIAGNOSTIC if (ra->ra_nreg < P9100_NREG) { printf(": expected %d registers, got only %d\n", P9100_NREG, ra->ra_nreg); return; } #endif sc->sc_flags = SCF_INTERNAL; sc->sc_mapmode = WSDISPLAYIO_MODE_EMUL; bcopy(ra->ra_reg, sc->sc_phys, sizeof(sc->sc_phys)); sc->sc_ctl = mapiodev(&ra->ra_reg[P9100_REG_CTL], 0, ra->ra_reg[P9100_REG_CTL].rr_len); sc->sc_cmd = mapiodev(&ra->ra_reg[P9100_REG_CMD], 0, ra->ra_reg[P9100_REG_CMD].rr_len); #ifdef FIDDLE_WITH_PCI_REGISTERS sc->sc_pci = (struct p9100_pci *) mapiodev(&ra->ra_reg[P9100_REG_CONFIG], 0, ra->ra_reg[P9100_REG_CONFIG].rr_len); #endif node = ra->ra_node; isconsole = node == fbnode; P9100_SELECT_SCR(sc); scr = P9100_READ_CTL(sc, P9000_SYSTEM_CONFIG); switch (scr & SCR_PIXEL_MASK) { default: #ifdef DIAGNOSTIC printf(": unknown color depth code 0x%x", scr & SCR_PIXEL_MASK); #endif /* FALLTHROUGH */ case SCR_PIXEL_32BPP: case SCR_PIXEL_24BPP: case SCR_PIXEL_16BPP: force_reset = 1; break; case SCR_PIXEL_8BPP: force_reset = 0; break; } fb_setsize(&sc->sc_sunfb, 8, LCD_WIDTH, LCD_HEIGHT, node, ca->ca_bustype); #if 0 /* * The PROM will initialize us in 800x600x8 mode anyway. If it * does not, we'll force this mode right now. */ if (sc->sc_sunfb.sf_width != LCD_WIDTH || sc->sc_sunfb.sf_depth != 8 || sc->sc_sunfb.sf_height != LCD_HEIGHT || force_reset != 0) { sc->sc_sunfb.sf_width = LCD_WIDTH; sc->sc_sunfb.sf_height = LCD_HEIGHT; sc->sc_sunfb.sf_depth = 8; sc->sc_sunfb.sf_linebytes = LCD_WIDTH; printf("\n"); p9100_initialize_ramdac(sc, LCD_WIDTH, 8); printf("%s", self->dv_xname); clear = 1; } #endif #if NTCTRL > 0 /* * We want to run the frame buffer in 8bpp mode for the emulation mode, * and use a potentially better mode for the mapped (X11) mode. * Eventually this will become runtime user-selectable. */ sc->sc_mapwidth = LCD_WIDTH; sc->sc_mapheight = LCD_HEIGHT; sc->sc_mapdepth = 8; if (sc->sc_mapwidth != sc->sc_sunfb.sf_width || sc->sc_mapdepth != sc->sc_sunfb.sf_depth) SET(sc->sc_flags, SCF_MAPPEDSWITCH); #endif ri->ri_bits = mapiodev(&ra->ra_reg[P9100_REG_VRAM], 0, sc->sc_vramsize = round_page(ra->ra_reg[P9100_REG_VRAM].rr_len)); ri->ri_hw = sc; printf(": rev %x, %dx%d\n", scr & SCR_ID_MASK, LCD_WIDTH, LCD_HEIGHT); /* Disable frame buffer interrupts */ P9100_SELECT_SCR(sc); P9100_WRITE_CTL(sc, P9000_INTERRUPT_ENABLE, IER_MASTER_ENABLE | 0); sc->sc_ih.ih_fun = p9100_intr; sc->sc_ih.ih_arg = sc; intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname); /* * Try to get a copy of the PROM font. * * If we can, we still need to adjust the visible portion of the * display, as the PROM output is offset two chars to the left. * * If we can't, we'll switch to the 8x16 font, and we'll need to adjust * two things: * - 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 */ fontswitch = p9100_pick_romfont(sc); /* * Register the external video control callback with tctrl; tctrl * will invoke it immediately to set the appropriate behaviour. * If tctrl is not configured, simply enable external video. */ #if NTCTRL > 0 tadpole_register_extvideo(p9100_external_video, sc); #else p9100_external_video(sc, 1); #endif if (isconsole == 0 || fontswitch) clear = 1; fbwscons_init(&sc->sc_sunfb, clear ? RI_CLEAR : 0); if (clear == 0) { ri->ri_bits -= 2 * ri->ri_xscale; ri->ri_xorigin -= 2 * ri->ri_xscale; } fbwscons_setcolormap(&sc->sc_sunfb, p9100_setcolor); /* * Plug-in accelerated console operations. */ if (sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags != 0) p9100_ras_init(sc); /* enable video */ p9100_burner(sc, 1, 0); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, clear ? 0 : -1); #if NTCTRL > 0 shutdownhook_establish(p9100_prom, sc); #endif } fbwscons_attach(&sc->sc_sunfb, &p9100_accessops, isconsole); }
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 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 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); }
/* * 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); }
/* * 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); }