/* * Probe for a pfour framebuffer. Return values: * * PFOUR_NOTPFOUR: framebuffer is not a pfour framebuffer * otherwise returns pfour ID */ int fb_pfour_id(volatile void *va) { #if defined(SUN4) volatile u_int32_t val, save, *pfour = va; /* Read the pfour register. */ save = *pfour; /* * Try to modify the type code. If it changes, put the * original value back, and notify the caller that it's * not a pfour framebuffer. */ val = save & ~PFOUR_REG_RESET; *pfour = (val ^ PFOUR_FBTYPE_MASK); if ((*pfour ^ val) & PFOUR_FBTYPE_MASK) { *pfour = save; return (PFOUR_NOTPFOUR); } return (PFOUR_ID(val)); #else return (PFOUR_NOTPFOUR); #endif /* SUN4 */ }
void fb_setsize(struct sunfb *sf, int def_depth, int def_width, int def_height, int node, int bustype) { int def_linebytes; switch (bustype) { case BUS_VME16: case BUS_VME32: case BUS_OBIO: #if defined(SUN4M) /* 4m may have SBus-like framebuffer on obio */ if (CPU_ISSUN4M) { goto obpsize; } #endif /* Set up some defaults. */ sf->sf_width = def_width; sf->sf_height = def_height; sf->sf_depth = def_depth; #if defined(SUN4) /* * This is not particularly useful on Sun 4 VME framebuffers. * The EEPROM only contains info about the built-in. */ if (CPU_ISSUN4 && bustype == BUS_OBIO) { struct eeprom *eep = (struct eeprom *)eeprom_va; if (ISSET(sf->sf_flags, FB_PFOUR)) { volatile u_int32_t pfour; u_int size; pfour = *sf->sf_pfour; /* * Use the pfour register to determine * the size. Note that the cgsix and * cgeight don't use this size encoding. * In this case, we have to settle * for the defaults we were provided * with. */ if ((PFOUR_ID(pfour) == PFOUR_ID_COLOR24) || (PFOUR_ID(pfour) == PFOUR_ID_FASTCOLOR)) size = 0x00; /* invalid */ else size = PFOUR_SIZE(pfour); switch (size) { case PFOUR_SIZE_1152X900: sf->sf_width = 1152; sf->sf_height = 900; break; case PFOUR_SIZE_1024X1024: sf->sf_width = 1024; sf->sf_height = 1024; break; case PFOUR_SIZE_1280X1024: sf->sf_width = 1280; sf->sf_height = 1024; break; case PFOUR_SIZE_1600X1280: sf->sf_width = 1600; sf->sf_height = 1280; break; case PFOUR_SIZE_1440X1440: sf->sf_width = 1440; sf->sf_height = 1440; break; case PFOUR_SIZE_640X480: sf->sf_width = 640; sf->sf_height = 480; break; } } else if (eep != NULL) { switch (eep->eeScreenSize) { case EE_SCR_1152X900: sf->sf_width = 1152; sf->sf_height = 900; break; case EE_SCR_1024X1024: sf->sf_width = 1024; sf->sf_height = 1024; break; case EE_SCR_1600X1280: sf->sf_width = 1600; sf->sf_height = 1280; break; case EE_SCR_1440X1440: sf->sf_width = 1440; sf->sf_height = 1440; break; } } } #endif /* SUN4 */ #if defined(SUN4M) if (CPU_ISSUN4M) { /* XXX: need code to find 4/600 vme screen size */ } #endif /* SUN4M */ sf->sf_linebytes = (sf->sf_width * sf->sf_depth) / 8; break; case BUS_SBUS: #if defined(SUN4M) obpsize: #endif sf->sf_depth = getpropint(node, "depth", def_depth); sf->sf_width = getpropint(node, "width", def_width); sf->sf_height = getpropint(node, "height", def_height); def_linebytes = roundup(sf->sf_width, sf->sf_depth) * sf->sf_depth / 8; sf->sf_linebytes = getpropint(node, "linebytes", def_linebytes); /* * XXX If we are configuring a board in a wider depth level * than the mode it is currently operating in, the PROM will * return a linebytes property tied to the current depth value, * which is NOT what we are relying upon! */ if (sf->sf_linebytes < (sf->sf_width * sf->sf_depth) / 8) sf->sf_linebytes = def_linebytes; break; } sf->sf_fbsize = sf->sf_height * sf->sf_linebytes; }
static void bwtwoattach_obio(device_t parent, device_t self, void *aux) { struct bwtwo_softc *sc = device_private(self); union obio_attach_args *uoba = aux; struct obio4_attach_args *oba; struct fbdevice *fb = &sc->sc_fb; struct eeprom *eep = (struct eeprom *)eeprom_va; bus_space_handle_t bh; int constype, isconsole; const char *name; sc->sc_dev = self; oba = &uoba->uoba_oba4; /* Remember cookies for bwtwo_mmap() */ sc->sc_bustag = oba->oba_bustag; sc->sc_paddr = (bus_addr_t)oba->oba_paddr; fb->fb_flags = device_cfdata(self)->cf_flags; fb->fb_type.fb_depth = 1; fb_setsize_eeprom(fb, fb->fb_type.fb_depth, 1152, 900); constype = (fb->fb_flags & FB_PFOUR) ? EE_CONS_P4OPT : EE_CONS_BW; if (eep == NULL || eep->eeConsole == constype) isconsole = fb_is_console(0); else isconsole = 0; if (fb->fb_flags & FB_PFOUR) { /* * Map the pfour control register. * Set pixel offset to appropriate overlay plane. */ name = "bwtwo/p4"; if (bus_space_map(oba->oba_bustag, oba->oba_paddr, sizeof(uint32_t), BUS_SPACE_MAP_LINEAR, &bh) != 0) { printf("%s: cannot map pfour register\n", device_xname(self)); return; } fb->fb_pfour = (uint32_t *)bh; sc->sc_reg = NULL; /* * Notice if this is an overlay plane on a color * framebuffer. Note that PFOUR_COLOR_OFF_OVERLAY * is the same as PFOUR_BW_OFF, but we use the * different names anyway. */ switch (PFOUR_ID(*fb->fb_pfour)) { case PFOUR_ID_COLOR8P1: sc->sc_ovtype = BWO_CGFOUR; sc->sc_pixeloffset = PFOUR_COLOR_OFF_OVERLAY; break; case PFOUR_ID_COLOR24: sc->sc_ovtype = BWO_CGEIGHT; sc->sc_pixeloffset = PFOUR_COLOR_OFF_OVERLAY; break; default: sc->sc_ovtype = BWO_NONE; sc->sc_pixeloffset = PFOUR_BW_OFF; break; } } else { /* A plain bwtwo */ if (bus_space_map(oba->oba_bustag, oba->oba_paddr + BWREG_REG, sizeof(struct fbcontrol), BUS_SPACE_MAP_LINEAR, &bh) != 0) { printf("%s: cannot map control registers\n", device_xname(self)); return; } sc->sc_reg = (struct fbcontrol *)bh; fb->fb_pfour = NULL; name = "bwtwo"; sc->sc_pixeloffset = BWREG_MEM; } sc->sc_get_video = bwtwo_get_video_sun4; sc->sc_set_video = bwtwo_set_video_sun4; if (isconsole) { int ramsize = fb->fb_type.fb_height * fb->fb_linebytes; if (bus_space_map(oba->oba_bustag, oba->oba_paddr + sc->sc_pixeloffset, ramsize, BUS_SPACE_MAP_LINEAR, &bh) != 0) { printf("%s: cannot map pixels\n", device_xname(self)); return; } sc->sc_fb.fb_pixels = (char *)bh; } bwtwoattach(sc, name, isconsole); }
void fb_setsize_pfour(struct fbdevice *fb) { #if defined(SUN4) volatile u_int32_t pfour; int width, height; /* * Some pfour framebuffers, e.g. the * cgsix, don't encode resolution the * same, so the driver handles that. * The driver can let us know that it * needs to do this by not mapping in * the pfour register by the time this * routine is called. */ if (fb->fb_pfour == NULL) return; pfour = *fb->fb_pfour; /* * Use the pfour register to determine * the size. Note that the cgsix and * cgeight don't use this size encoding. * In this case, we have to settle * for the defaults we were provided * with. */ if ((PFOUR_ID(pfour) == PFOUR_ID_COLOR24) || (PFOUR_ID(pfour) == PFOUR_ID_FASTCOLOR)) return; switch (PFOUR_SIZE(pfour)) { case PFOUR_SIZE_1152X900: width = 1152; height = 900; break; case PFOUR_SIZE_1024X1024: width = 1024; height = 1024; break; case PFOUR_SIZE_1280X1024: width = 1280; height = 1024; break; case PFOUR_SIZE_1600X1280: width = 1600; height = 1280; break; case PFOUR_SIZE_1440X1440: width = 1440; height = 1440; break; case PFOUR_SIZE_640X480: width = 640; height = 480; break; default: /* * Use the defaults already filled in by the generic fb code. */ return; } fb->fb_type.fb_width = width; fb->fb_type.fb_height = height; #endif /* SUN4 */ }