void wdc_obio_attach(device_t parent, device_t self, void *aux) { struct wdc_obio_softc *sc = device_private(self); struct wdc_regs *wdr; struct confargs *ca = aux; struct ata_channel *chp = &sc->sc_channel; int intr, i, type = IST_EDGE; int use_dma = 0; char path[80]; sc->sc_wdcdev.sc_atac.atac_dev = self; if (device_cfdata(sc->sc_wdcdev.sc_atac.atac_dev)->cf_flags & WDC_OPTIONS_DMA) { if (ca->ca_nreg >= 16 || ca->ca_nintr == -1) use_dma = 1; /* XXX Don't work yet. */ } if (ca->ca_nintr >= 4 && ca->ca_nreg >= 8) { intr = ca->ca_intr[0]; aprint_normal(" irq %d", intr); if (ca->ca_nintr > 8) { type = ca->ca_intr[1] ? IST_LEVEL : IST_EDGE; } aprint_normal(", %s triggered", (type == IST_EDGE) ? "edge" : "level"); } else if (ca->ca_nintr == -1) { intr = WDC_DEFAULT_PIO_IRQ; aprint_normal(" irq property not found; using %d", intr); } else { aprint_error(": couldn't get irq property\n"); return; } if (use_dma) aprint_normal(": DMA transfer"); aprint_normal("\n"); sc->sc_wdcdev.regs = wdr = &sc->sc_wdc_regs; wdr->cmd_iot = wdr->ctl_iot = ca->ca_tag; if (bus_space_map(wdr->cmd_iot, ca->ca_baseaddr + ca->ca_reg[0], WDC_REG_NPORTS << 4, 0, &wdr->cmd_baseioh) || bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, WDC_AUXREG_OFFSET << 4, 1, &wdr->ctl_ioh)) { aprint_error_dev(self, "couldn't map registers\n"); return; } for (i = 0; i < WDC_NREG; i++) { if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, i << 4, i == 0 ? 4 : 1, &wdr->cmd_iohs[i]) != 0) { bus_space_unmap(wdr->cmd_iot, wdr->cmd_baseioh, WDC_REG_NPORTS << 4); aprint_error_dev(self, "couldn't subregion registers\n"); return; } } #if 0 wdr->data32iot = wdr->cmd_iot; wdr->data32ioh = wdr->cmd_ioh; #endif sc->sc_ih = intr_establish(intr, type, IPL_BIO, wdcintr, chp); if (use_dma) { sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20); /* * XXX * we don't use ca->ca_reg[3] for size here because at least * on the PB3400c it says 0x200 for both IDE channels ( the * one on the mainboard and the other on the mediabay ) but * their start addresses are only 0x100 apart. Since those * DMA registers are always 0x100 or less we don't really * have to care though */ if (bus_space_map(wdr->cmd_iot, ca->ca_baseaddr + ca->ca_reg[2], 0x100, BUS_SPACE_MAP_LINEAR, &sc->sc_dmaregh)) { aprint_error_dev(self, "unable to map DMA registers (%08x)\n", ca->ca_reg[2]); /* should unmap stuff here */ return; } sc->sc_dmareg = bus_space_vaddr(wdr->cmd_iot, sc->sc_dmaregh); sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA; sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; if (strcmp(ca->ca_name, "ata-4") == 0) { sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA; sc->sc_wdcdev.sc_atac.atac_udma_cap = 4; sc->sc_wdcdev.sc_atac.atac_set_modes = ata4_adjust_timing; } else { sc->sc_wdcdev.sc_atac.atac_set_modes = adjust_timing; } #ifdef notyet /* Minimum cycle time is 150ns (DMA MODE 1) on ohare. */ if (ohare) { sc->sc_wdcdev.sc_atac.atac_pio_cap = 3; sc->sc_wdcdev.sc_atac.atac_dma_cap = 1; } #endif } else { /* all non-DMA controllers can use adjust_timing */ sc->sc_wdcdev.sc_atac.atac_set_modes = adjust_timing; } sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16; sc->sc_chanptr = chp; sc->sc_wdcdev.sc_atac.atac_channels = &sc->sc_chanptr; sc->sc_wdcdev.sc_atac.atac_nchannels = 1; sc->sc_wdcdev.wdc_maxdrives = 2; sc->sc_wdcdev.dma_arg = sc; sc->sc_wdcdev.dma_init = wdc_obio_dma_init; sc->sc_wdcdev.dma_start = wdc_obio_dma_start; sc->sc_wdcdev.dma_finish = wdc_obio_dma_finish; chp->ch_channel = 0; chp->ch_atac = &sc->sc_wdcdev.sc_atac; chp->ch_queue = &sc->sc_chqueue; wdc_init_shadow_regs(chp); #define OHARE_FEATURE_REG 0xf3000038 /* XXX Enable wdc1 by feature reg. */ memset(path, 0, sizeof(path)); OF_package_to_path(ca->ca_node, path, sizeof(path)); if (strcmp(path, "/bandit@F2000000/ohare@10/ata@21000") == 0) { u_int x; x = in32rb(OHARE_FEATURE_REG); x |= 8; out32rb(OHARE_FEATURE_REG, x); } wdcattach(chp); }
static int intelfb_create(struct intel_fbdev *ifbdev, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = ifbdev->helper.dev; struct drm_i915_private *dev_priv = dev->dev_private; #if 0 struct fb_info *info; #endif struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd = {}; struct drm_i915_gem_object *obj; int size, ret; /* we don't do packed 24bpp */ if (sizes->surface_bpp == 24) sizes->surface_bpp = 32; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = roundup2(mode_cmd.width * ((sizes->surface_bpp + 7) / 8), 64); mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = mode_cmd.pitches[0] * mode_cmd.height; size = roundup2(size, PAGE_SIZE); obj = i915_gem_alloc_object(dev, size); if (!obj) { DRM_ERROR("failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } DRM_LOCK(); /* Flush everything out, we'll be doing GTT only from now on */ ret = intel_pin_and_fence_fb_obj(dev, obj, false); if (ret) { DRM_ERROR("failed to pin fb: %d\n", ret); goto out_unref; } #if 0 info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_unpin; } info->par = ifbdev; #endif ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); if (ret) goto out_unpin; fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; #if 0 ifbdev->helper.fbdev = info; strlcpy(info->fix.id, "inteldrmfb", sizeof(info->fix.id)); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unpin; } /* setup aperture base/size for vesafb takeover */ info->apertures = alloc_apertures(1); if (!info->apertures) { ret = -ENOMEM; goto out_unpin; } info->apertures->ranges[0].base = dev->mode_config.fb_base; info->apertures->ranges[0].size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; info->fix.smem_len = size; info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; } info->screen_size = size; // memset(info->screen_base, 0, size); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ #else { struct rasops_info *ri = &dev_priv->ro; bus_space_handle_t bsh; int err; err = agp_map_subregion(dev_priv->agph, obj->gtt_offset, size, &bsh); if (err) { ret = -err; goto out_unpin; } ri->ri_bits = bus_space_vaddr(dev->bst, bsh); ri->ri_depth = fb->bits_per_pixel; ri->ri_stride = fb->pitches[0]; ri->ri_width = sizes->fb_width; ri->ri_height = sizes->fb_height; switch (fb->pixel_format) { case DRM_FORMAT_XRGB8888: ri->ri_rnum = 8; ri->ri_rpos = 16; ri->ri_gnum = 8; ri->ri_gpos = 8; ri->ri_bnum = 8; ri->ri_bpos = 0; break; case DRM_FORMAT_RGB565: ri->ri_rnum = 5; ri->ri_rpos = 11; ri->ri_gnum = 6; ri->ri_gpos = 5; ri->ri_bnum = 5; ri->ri_bpos = 0; break; } } #endif DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", fb->width, fb->height, obj->gtt_offset, obj); DRM_UNLOCK(); #if 1 DRM_DEBUG_KMS("skipping call to vga_switcheroo_client_fb_set\n"); #else vga_switcheroo_client_fb_set(dev->pdev, info); #endif return 0; out_unpin: i915_gem_object_unpin(obj); out_unref: drm_gem_object_unreference(&obj->base); DRM_UNLOCK(); out: return ret; }
/* * 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 * initalized by the PROM - do this ourselves. */ if (!isconsole) { if (rfx_initialize(sc, sa, &cf) != 0) return; } fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR); bzero(&sc->sc_cmap, sizeof(sc->sc_cmap)); fbwscons_setcolormap(&sc->sc_sunfb, rfx_setcolor); if (isconsole) { fbwscons_console_init(&sc->sc_sunfb, -1); } /* enable video */ rfx_burner(sc, 1, 0); fbwscons_attach(&sc->sc_sunfb, &rfx_accessops, isconsole); }
void 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: ; }
/* * 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); }