diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2009-02-24 14:37:30 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2009-02-24 14:37:30 +0000 |
commit | 9e586790ff21037cc452a30919083aa42150e7c4 (patch) | |
tree | d55c413fcda34f21b281af81a0db8b97bd4be589 /sys | |
parent | 6e4fb64a50346b502c07802b72bfa44ab2df4a06 (diff) |
Add support for hardware acceleration to gbe(4). This provides an accelerated
framebuffer for the console on SGI O2 workstations. X is still supported via
wsfb(4) by switching back to the unaccelerated linear framebuffer mode.
Some hardware details and magic numbers from NetBSD's crmfb(4) driver.
ok miod@ jasper@ "Sure, go for it" deraadt@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sgi/dev/gbe.c | 555 | ||||
-rw-r--r-- | sys/arch/sgi/dev/gbereg.h | 107 |
2 files changed, 599 insertions, 63 deletions
diff --git a/sys/arch/sgi/dev/gbe.c b/sys/arch/sgi/dev/gbe.c index eca78c98b55..734a36d027c 100644 --- a/sys/arch/sgi/dev/gbe.c +++ b/sys/arch/sgi/dev/gbe.c @@ -1,7 +1,7 @@ -/* $OpenBSD: gbe.c,v 1.6 2008/04/07 22:34:21 miod Exp $ */ +/* $OpenBSD: gbe.c,v 1.7 2009/02/24 14:37:29 jsing Exp $ */ /* - * Copyright (c) 2007, Joel Sing <jsing@openbsd.org> + * Copyright (c) 2007, 2008, 2009 Joel Sing <jsing@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,7 +17,7 @@ */ /* - * Graphics Back End (GBE) Framebuffer for SGI O2 + * Graphics Back End (GBE) Framebuffer for SGI O2. */ #include <sys/param.h> @@ -60,7 +60,8 @@ struct gbe_cmap { struct gbe_screen { struct device *sc; /* Back pointer. */ - struct rasops_info ri; /* Raster display info. */ + struct rasops_info ri; /* Screen raster display info. */ + struct rasops_info ri_tile; /* Raster info for rasops tile. */ struct gbe_cmap cmap; /* Display colour map. */ int fb_size; /* Size of framebuffer memory. */ @@ -70,11 +71,16 @@ struct gbe_screen { paddr_t tm_phys; /* Physical address of tilemap. */ caddr_t fb; /* Address of framebuffer memory. */ paddr_t fb_phys; /* Physical address of framebuffer. */ + caddr_t ro; /* Address of rasops tile. */ + paddr_t ro_phys; /* Physical address of rasops tile. */ int width; /* Width in pixels. */ int height; /* Height in pixels. */ int depth; /* Colour depth in bits. */ + int mode; /* Display mode. */ + int bufmode; /* Rendering engine buffer mode. */ int linebytes; /* Bytes per line. */ + int ro_curpos; /* Current position in rasops tile. */ }; /* @@ -84,7 +90,8 @@ struct gbe_softc { struct device sc_dev; bus_space_tag_t iot; - bus_space_handle_t ioh; + bus_space_handle_t ioh; /* GBE registers. */ + bus_space_handle_t re_ioh; /* Rendering engine registers. */ bus_dma_tag_t dmat; int rev; /* Hardware revision. */ @@ -102,6 +109,7 @@ void gbe_enable(struct gbe_softc *); void gbe_disable(struct gbe_softc *); void gbe_setup(struct gbe_softc *); void gbe_setcolour(struct gbe_softc *, u_int, u_int8_t, u_int8_t, u_int8_t); +void gbe_wait_re_idle(struct gbe_softc *); /* * Colour map handling for indexed modes. @@ -122,6 +130,19 @@ int gbe_show_screen(void *, void *, int, void (*)(void *, int, int), void *); void gbe_burner(void *, u_int, u_int); +/* + * Hardware acceleration for rasops. + */ +void gbe_rop(struct gbe_softc *, int, int, int, int, int); +void gbe_copyrect(struct gbe_softc *, int, int, int, int, int, int, int); +void gbe_fillrect(struct gbe_softc *, int, int, int, int, int); +void gbe_do_cursor(struct rasops_info *); +void gbe_putchar(void *, int, int, u_int, long); +void gbe_copycols(void *, int, int, int, int); +void gbe_erasecols(void *, int, int, int, long); +void gbe_copyrows(void *, int, int, int); +void gbe_eraserows(void *, int, int, long); + static struct gbe_screen gbe_consdata; static int gbe_console; @@ -180,10 +201,13 @@ gbe_attach(struct device *parent, struct device *self, void *aux) struct wsemuldisplaydev_attach_args waa; bus_dma_segment_t tm_segs[1]; bus_dma_segment_t fb_segs[1]; + bus_dma_segment_t ro_segs[1]; bus_dmamap_t tm_dmamap; bus_dmamap_t fb_dmamap; + bus_dmamap_t ro_dmamap; int tm_nsegs; int fb_nsegs; + int ro_nsegs; uint32_t val; long attr; @@ -202,6 +226,8 @@ gbe_attach(struct device *parent, struct device *self, void *aux) */ gsc->ioh = PHYS_TO_UNCACHED(GBE_BASE); + gsc->re_ioh = PHYS_TO_UNCACHED(RE_BASE); + gsc->rev = bus_space_read_4(gsc->iot, gsc->ioh, GBE_CTRL_STAT) & 0xf; @@ -235,14 +261,20 @@ gbe_attach(struct device *parent, struct device *self, void *aux) screen = gsc->curscr; /* - * Setup bus space mapping. + * Setup bus space mappings. */ if (bus_space_map(gsc->iot, GBE_BASE - CRIMEBUS_BASE, GBE_REG_SIZE, BUS_SPACE_MAP_LINEAR, &gsc->ioh)) { - printf("failed to map bus space!\n"); + printf("failed to map framebuffer bus space!\n"); return; } + if (bus_space_map(gsc->iot, RE_BASE - CRIMEBUS_BASE, RE_REG_SIZE, + BUS_SPACE_MAP_LINEAR, &gsc->re_ioh)) { + printf("failed to map rendering engine bus space!\n"); + goto fail0; + } + /* Determine GBE revision. */ gsc->rev = bus_space_read_4(gsc->iot, gsc->ioh, GBE_CTRL_STAT) & 0xf; @@ -254,7 +286,7 @@ gbe_attach(struct device *parent, struct device *self, void *aux) if (screen->width == 0 || screen->height == 0) { printf("device has not been setup by firmware!\n"); - goto fail0; + goto fail1; } /* Setup screen defaults. */ @@ -264,30 +296,30 @@ gbe_attach(struct device *parent, struct device *self, void *aux) screen->linebytes = screen->width * screen->depth / 8; /* - * Setup DMA for tile map. + * Setup DMA for tilemap. */ if (bus_dmamap_create(gsc->dmat, screen->tm_size, 1, screen->tm_size, 0, BUS_DMA_NOWAIT, &tm_dmamap)) { - printf("failed to create DMA map for tile map!\n"); - goto fail0; + printf("failed to create DMA map for tilemap!\n"); + goto fail1; } if (bus_dmamem_alloc(gsc->dmat, screen->tm_size, 65536, 0, tm_segs, 1, &tm_nsegs, BUS_DMA_NOWAIT)) { - printf("failed to allocate DMA memory for tile map!\n"); - goto fail1; + printf("failed to allocate DMA memory for tilemap!\n"); + goto fail2; } if (bus_dmamem_map(gsc->dmat, tm_segs, tm_nsegs, screen->tm_size, &screen->tm, BUS_DMA_COHERENT)) { - printf("failed to map DMA memory for tile map!\n"); - goto fail2; + printf("failed to map DMA memory for tilemap!\n"); + goto fail3; } if (bus_dmamap_load(gsc->dmat, tm_dmamap, screen->tm, screen->tm_size, NULL, BUS_DMA_NOWAIT)){ printf("failed to load DMA map for tilemap\n"); - goto fail3; + goto fail4; } /* @@ -296,29 +328,57 @@ gbe_attach(struct device *parent, struct device *self, void *aux) if (bus_dmamap_create(gsc->dmat, screen->fb_size, 1, screen->fb_size, 0, BUS_DMA_NOWAIT, &fb_dmamap)) { printf("failed to create DMA map for framebuffer!\n"); - goto fail4; + goto fail5; } if (bus_dmamem_alloc(gsc->dmat, screen->fb_size, 65536, 0, fb_segs, 1, &fb_nsegs, BUS_DMA_NOWAIT)) { printf("failed to allocate DMA memory for framebuffer!\n"); - goto fail5; + goto fail6; } if (bus_dmamem_map(gsc->dmat, fb_segs, fb_nsegs, screen->fb_size, &screen->fb, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { printf("failed to map DMA memory for framebuffer!\n"); - goto fail6; + goto fail7; } if (bus_dmamap_load(gsc->dmat, fb_dmamap, screen->fb, screen->fb_size, NULL, BUS_DMA_NOWAIT)) { printf("failed to load DMA map for framebuffer\n"); - goto fail7; + goto fail8; + } + + /* + * Setup DMA for rasops tile. + */ + if (bus_dmamap_create(gsc->dmat, GBE_TILE_SIZE, 1, GBE_TILE_SIZE, + 0, BUS_DMA_NOWAIT, &ro_dmamap)) { + printf("failed to create DMA map for rasops tile!\n"); + goto fail9; + } + + if (bus_dmamem_alloc(gsc->dmat, GBE_TILE_SIZE, 65536, 0, ro_segs, + 1, &ro_nsegs, BUS_DMA_NOWAIT)) { + printf("failed to allocate DMA memory for rasops tile!\n"); + goto fail10; + } + + if (bus_dmamem_map(gsc->dmat, ro_segs, ro_nsegs, GBE_TILE_SIZE, + &screen->ro, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { + printf("failed to map DMA memory for rasops tile!\n"); + goto fail11; + } + + if (bus_dmamap_load(gsc->dmat, ro_dmamap, screen->ro, GBE_TILE_SIZE, + NULL, BUS_DMA_NOWAIT)) { + printf("failed to load DMA map for rasops tile\n"); + goto fail12; } screen->tm_phys = tm_dmamap->dm_segs[0].ds_addr; screen->fb_phys = fb_dmamap->dm_segs[0].ds_addr; + screen->ro_phys = ro_dmamap->dm_segs[0].ds_addr; shutdownhook_establish((void(*)(void *))gbe_disable, self); @@ -331,6 +391,9 @@ gbe_attach(struct device *parent, struct device *self, void *aux) if (screen->depth == 8) gbe_loadcmap(screen, 0, 255); + /* Clear framebuffer. */ + gbe_fillrect(gsc, 0, 0, screen->width, screen->height, 0); + printf("rev %u, %iMB, %dx%d at %d bits\n", gsc->rev, screen->fb_size >> 20, screen->width, screen->height, screen->depth); @@ -354,20 +417,30 @@ gbe_attach(struct device *parent, struct device *self, void *aux) return; -fail7: +fail12: + bus_dmamem_unmap(gsc->dmat, screen->ro, GBE_TILE_SIZE); +fail11: + bus_dmamem_free(gsc->dmat, ro_segs, ro_nsegs); +fail10: + bus_dmamap_destroy(gsc->dmat, ro_dmamap); +fail9: + bus_dmamap_unload(gsc->dmat, fb_dmamap); +fail8: bus_dmamem_unmap(gsc->dmat, screen->fb, screen->fb_size); -fail6: +fail7: bus_dmamem_free(gsc->dmat, fb_segs, fb_nsegs); -fail5: +fail6: bus_dmamap_destroy(gsc->dmat, fb_dmamap); -fail4: +fail5: bus_dmamap_unload(gsc->dmat, tm_dmamap); -fail3: +fail4: bus_dmamem_unmap(gsc->dmat, screen->tm, screen->tm_size); -fail2: +fail3: bus_dmamem_free(gsc->dmat, tm_segs, tm_nsegs); -fail1: +fail2: bus_dmamap_destroy(gsc->dmat, tm_dmamap); +fail1: + bus_space_unmap(gsc->iot, gsc->re_ioh, RE_REG_SIZE); fail0: bus_space_unmap(gsc->iot, gsc->ioh, GBE_REG_SIZE); } @@ -383,11 +456,14 @@ gbe_init_screen(struct gbe_screen *screen) int i; /* - * Initialise rasops. + * Initialise screen. */ + screen->mode = WSDISPLAYIO_MODE_EMUL; + + /* Initialise rasops. */ memset(&screen->ri, 0, sizeof(struct rasops_info)); - screen->ri.ri_flg = RI_CENTER | RI_CLEAR; + screen->ri.ri_flg = RI_CENTER; screen->ri.ri_depth = screen->depth; screen->ri.ri_width = screen->width; screen->ri.ri_height = screen->height; @@ -412,6 +488,28 @@ gbe_init_screen(struct gbe_screen *screen) rasops_init(&screen->ri, screen->height / 8, screen->width / 8); + /* Create a rasops instance that can draw into a single tile. */ + memcpy(&screen->ri_tile, &screen->ri, sizeof(struct rasops_info)); + screen->ri_tile.ri_flg = 0; + screen->ri_tile.ri_width = GBE_TILE_WIDTH >> (screen->depth >> 4); + screen->ri_tile.ri_height = GBE_TILE_HEIGHT; + screen->ri_tile.ri_stride = screen->ri_tile.ri_width * + screen->depth / 8; + screen->ri_tile.ri_xorigin = 0; + screen->ri_tile.ri_yorigin = 0; + screen->ri_tile.ri_bits = screen->ro; + screen->ri_tile.ri_origbits = screen->ro; + screen->ro_curpos = 0; + + screen->ri.ri_hw = screen->sc; + + screen->ri.ri_do_cursor = gbe_do_cursor; + screen->ri.ri_ops.putchar = gbe_putchar; + screen->ri.ri_ops.copyrows = gbe_copyrows; + screen->ri.ri_ops.copycols = gbe_copycols; + screen->ri.ri_ops.eraserows = gbe_eraserows; + screen->ri.ri_ops.erasecols = gbe_erasecols; + gbe_stdscreen.ncols = screen->ri.ri_cols; gbe_stdscreen.nrows = screen->ri.ri_rows; gbe_stdscreen.textops = &screen->ri.ri_ops; @@ -420,15 +518,16 @@ gbe_init_screen(struct gbe_screen *screen) gbe_stdscreen.capabilities = screen->ri.ri_caps; /* - * Map framebuffer into tile map. Each entry in the tilemap is 16 bits + * Map framebuffer into tilemap. Each entry in the tilemap is 16 bits * wide. Each tile is 64KB or 2^16 bits, hence the last 16 bits of the * address will range from 0x0000 to 0xffff. As a result we simply * discard the lower 16 bits and store bits 17 through 32 as an entry * in the tilemap. */ tm = (void *)screen->tm; - for (i = 0; i < (screen->fb_size >> GBE_TILE_SHIFT); i++) - tm[i] = (screen->fb_phys >> GBE_TILE_SHIFT) + i; + for (i = 0; i < (screen->fb_size >> GBE_TILE_SHIFT) && + i < GBE_TLB_SIZE; i++) + tm[i] = (screen->fb_phys >> GBE_TILE_SHIFT) + i; } void @@ -462,7 +561,7 @@ gbe_enable(struct gbe_softc *gsc) if (i == 10000) printf("timeout unfreezing pixel counter!\n"); - /* Provide GBE with address of tile map and enable DMA. */ + /* Provide GBE with address of tilemap and enable DMA. */ bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_CTRL, ((screen->tm_phys >> 9) << GBE_FB_CTRL_TILE_PTR_SHIFT) | GBE_FB_CTRL_DMA_ENABLE); @@ -564,9 +663,11 @@ void gbe_setup(struct gbe_softc *gsc) { struct gbe_screen *screen = gsc->curscr; - uint32_t val; - int i, cmode; + int i, t, cmode, tile_width, tiles_x, tiles_y; u_char *colour; + uint16_t *tm; + uint32_t val; + uint64_t reg; /* * Setup framebuffer. @@ -574,25 +675,69 @@ gbe_setup(struct gbe_softc *gsc) switch (screen->depth) { case 32: cmode = GBE_CMODE_RGB8; + screen->bufmode = COLOUR_DEPTH_32 << BUFMODE_BUFDEPTH_SHIFT | + PIXEL_TYPE_RGB << BUFMODE_PIXTYPE_SHIFT | + COLOUR_DEPTH_32 << BUFMODE_PIXDEPTH_SHIFT; break; case 16: cmode = GBE_CMODE_ARGB5; + screen->bufmode = COLOUR_DEPTH_16 << BUFMODE_BUFDEPTH_SHIFT | + PIXEL_TYPE_RGBA << BUFMODE_PIXTYPE_SHIFT | + COLOUR_DEPTH_16 << BUFMODE_PIXDEPTH_SHIFT; break; case 8: default: cmode = GBE_CMODE_I8; + screen->bufmode = COLOUR_DEPTH_8 << BUFMODE_BUFDEPTH_SHIFT | + PIXEL_TYPE_CI << BUFMODE_PIXTYPE_SHIFT | + COLOUR_DEPTH_8 << BUFMODE_PIXDEPTH_SHIFT; break; } - /* Trick framebuffer into linear mode. */ - i = screen->width * screen->height / (512 / (screen->depth >> 3)); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_PIXEL, - i << GBE_FB_SIZE_PIXEL_HEIGHT_SHIFT); + /* Calculate tile width in bytes and screen size in tiles. */ + tile_width = GBE_TILE_WIDTH >> (screen->depth >> 4); + tiles_x = (screen->width + tile_width - 1) >> + (GBE_TILE_WIDTH_SHIFT - (screen->depth >> 4)); + tiles_y = (screen->height + GBE_TILE_HEIGHT - 1) >> + GBE_TILE_HEIGHT_SHIFT; - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, - (1 << GBE_FB_SIZE_TILE_WIDTH_SHIFT) | - ((screen->depth >> 4) << GBE_FB_SIZE_TILE_DEPTH_SHIFT)); - + if (screen->mode != WSDISPLAYIO_MODE_EMUL) { + + /* + * Setup the framebuffer in "linear" mode. We trick the + * framebuffer into linear mode by telling it that it is one + * tile wide and specifying an adjusted framebuffer height. + */ + + bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, + ((screen->depth >> 4) << GBE_FB_SIZE_TILE_DEPTH_SHIFT) | + (1 << GBE_FB_SIZE_TILE_WIDTH_SHIFT)); + + bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_PIXEL, + (screen->width * screen->height / tile_width) << + GBE_FB_SIZE_PIXEL_HEIGHT_SHIFT); + + } else { + + /* + * Setup the framebuffer in tiled mode. Provide the tile + * colour depth, screen width in whole and partial tiles, + * and the framebuffer height in pixels. + */ + + bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, + ((screen->depth >> 4) << GBE_FB_SIZE_TILE_DEPTH_SHIFT) | + ((screen->width / tile_width) << + GBE_FB_SIZE_TILE_WIDTH_SHIFT) | + ((screen->width % tile_width != 0) ? + (screen->height / GBE_TILE_HEIGHT) : 0)); + + bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_PIXEL, + screen->height << GBE_FB_SIZE_PIXEL_HEIGHT_SHIFT); + + } + + /* Set colour mode registers. */ val = (cmode << GBE_WID_MODE_SHIFT) | GBE_BMODE_BOTH; for (i = 0; i < (32 * 4); i += 4) bus_space_write_4(gsc->iot, gsc->ioh, GBE_MODE + i, val); @@ -623,6 +768,56 @@ gbe_setup(struct gbe_softc *gsc) GBE_GMAP + i * sizeof(u_int32_t), (i << 24) | (i << 16) | (i << 8)); + /* + * Initialise the rendering engine. + */ + val = screen->mode | BUF_TYPE_TLB_A << BUFMODE_BUFTYPE_SHIFT; + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_BUFMODE_SRC, val); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_BUFMODE_DST, val); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_CLIPMODE, 0); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_COLOUR_MASK, 0xffffffff); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PIXEL_XFER_X_STEP, 1); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PIXEL_XFER_Y_STEP, 1); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_WINOFFSET_DST, 0); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_WINOFFSET_SRC, 0); + + /* + * Load framebuffer tiles into TLB A. Each TLB consists of a 16x16 + * tile array representing 2048x2048 pixels. Each entry in the TLB + * consists of four 16-bit entries which represent bits 17:32 of the + * 64KB tile address. As a result, we can make use of the tilemap + * which already stores tile entries in the same format. + */ + tm = (void *)screen->tm; + for (i = 0, t = 0; i < GBE_TLB_SIZE; i++) { + reg <<= 16; + if (i % 16 < tiles_x) + reg |= (tm[t++] | 0x8000); + if (i % 4 == 3) + bus_space_write_8(gsc->iot, gsc->re_ioh, + RE_TLB_A + (i >> 2) * 8, reg); + } + + /* Load single tile into TLB B for rasops. */ + bus_space_write_8(gsc->iot, gsc->re_ioh, + RE_TLB_B, (screen->ro_phys >> 16 | 0x8000) << 48); +} + +void +gbe_wait_re_idle(struct gbe_softc *gsc) +{ + int i; + + /* Wait until rendering engine is idle. */ + for (i = 0; i < 100000; i++) { + if (bus_space_read_4(gsc->iot, gsc->re_ioh, RE_PP_STATUS) & + RE_PP_STATUS_IDLE) + break; + delay(1); + } + if (i == 100000) + printf("%s: rendering engine did not become idle!\n", + gsc->sc_dev.dv_xname); } /* @@ -633,7 +828,7 @@ int gbe_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) { struct gbe_screen *screen = (struct gbe_screen *)v; - int rc; + int rc, mode; switch (cmd) { case WSDISPLAYIO_GTYPE: @@ -678,6 +873,29 @@ gbe_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) } break; + case WSDISPLAYIO_GMODE: + *(u_int *)data = screen->mode; + break; + + case WSDISPLAYIO_SMODE: + mode = *(u_int *)data; + if (mode == WSDISPLAYIO_MODE_EMUL || + mode == WSDISPLAYIO_MODE_MAPPED || + mode == WSDISPLAYIO_MODE_DUMBFB) { + + screen->mode = mode; + + gbe_disable((struct gbe_softc *)screen->sc); + gbe_setup((struct gbe_softc *)screen->sc); + gbe_enable((struct gbe_softc *)screen->sc); + + /* Clear framebuffer if entering emulated mode. */ + if (screen->mode == WSDISPLAYIO_MODE_EMUL) + gbe_fillrect((struct gbe_softc *)screen->sc, + 0, 0, screen->width, screen->height, 0); + } + break; + case WSDISPLAYIO_GVIDEO: case WSDISPLAYIO_SVIDEO: /* Handled by the upper layer. */ @@ -824,6 +1042,215 @@ gbe_loadcmap(struct gbe_screen *screen, u_int start, u_int end) } /* + * Hardware accelerated functions for rasops. + */ + +void +gbe_rop(struct gbe_softc *gsc, int x, int y, int w, int h, int op) +{ + + gbe_wait_re_idle(gsc); + + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PRIMITIVE, + PRIMITIVE_RECTANGLE | PRIMITIVE_LRTB); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_DRAWMODE, + DRAWMODE_BITMASK | DRAWMODE_BYTEMASK | DRAWMODE_PIXEL_XFER | + DRAWMODE_LOGIC_OP); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_LOGIC_OP, op); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PIXEL_XFER_SRC, + (x << 16) | (y & 0xffff)); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_0, + (x << 16) | (y & 0xffff)); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_1 | RE_START, + ((x + w - 1) << 16) | ((y + h - 1) & 0xffff)); +} + +void +gbe_copyrect(struct gbe_softc *gsc, int src, int sx, int sy, int dx, int dy, + int w, int h) +{ + int direction, x0, y0, x1, y1; + + if (sx >= dx && sy >= dy) { + direction = PRIMITIVE_LRTB; + x0 = dx; + y0 = dy; + x1 = dx + w - 1; + y1 = dy + h - 1; + } else if (sx >= dx && sy < dy) { + direction = PRIMITIVE_LRBT; + sy = sy + h - 1; + x0 = dx; + y0 = dy + h - 1; + x1 = dx + w - 1; + y1 = dy; + } else if (sx < dx && sy >= dy) { + direction = PRIMITIVE_RLTB; + sx = sx + w - 1; + x0 = dx + w - 1; + y0 = dy; + x1 = dx; + y1 = dy + h - 1; + } else if (sx < dx && sy < dy) { + direction = PRIMITIVE_RLBT; + sy = sy + h - 1; + sx = sx + w - 1; + x0 = dx + w - 1; + y0 = dy + h - 1; + x1 = dx; + y1 = dy; + } + + gbe_wait_re_idle(gsc); + + if (src != BUF_TYPE_TLB_A) + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_BUFMODE_SRC, + gsc->curscr->bufmode | (src << BUFMODE_BUFTYPE_SHIFT)); + + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PRIMITIVE, + PRIMITIVE_RECTANGLE | direction); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_DRAWMODE, + DRAWMODE_BITMASK | DRAWMODE_BYTEMASK | DRAWMODE_PIXEL_XFER); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PIXEL_XFER_SRC, + (sx << 16) | (sy & 0xffff)); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_0, + (x0 << 16) | (y0 & 0xffff)); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_1 | RE_START, + (x1 << 16) | (y1 & 0xffff)); + + if (src != BUF_TYPE_TLB_A) { + gbe_wait_re_idle(gsc); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_BUFMODE_SRC, + gsc->curscr->bufmode | + (BUF_TYPE_TLB_A << BUFMODE_BUFTYPE_SHIFT)); + } +} + +void +gbe_fillrect(struct gbe_softc *gsc, int x, int y, int w, int h, int bg) +{ + + gbe_wait_re_idle(gsc); + + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PRIMITIVE, + PRIMITIVE_RECTANGLE | PRIMITIVE_LRTB); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_DRAWMODE, + DRAWMODE_BITMASK | DRAWMODE_BYTEMASK); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_SHADE_FG_COLOUR, bg); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_0, + (x << 16) | (y & 0xffff)); + bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_1 | RE_START, + ((x + w - 1) << 16) | ((y + h - 1) & 0xffff)); +} + +void +gbe_do_cursor(struct rasops_info *ri) +{ + struct gbe_softc *sc = ri->ri_hw; + int y, x, w, h; + + w = ri->ri_font->fontwidth; + h = ri->ri_font->fontheight; + x = ri->ri_xorigin + ri->ri_ccol * w; + y = ri->ri_yorigin + ri->ri_crow * h; + + gbe_rop(sc, x, y, w, h, LOGIC_OP_XOR); +} + +void +gbe_putchar(void *cookie, int row, int col, u_int uc, long attr) +{ + struct rasops_info *ri = cookie; + struct gbe_softc *gsc = ri->ri_hw; + struct gbe_screen *screen = gsc->curscr; + struct rasops_info *ri_tile = &screen->ri_tile; + int x, y, w, h; + + w = ri->ri_font->fontwidth; + h = ri->ri_font->fontheight; + x = ri->ri_xorigin + col * w; + y = ri->ri_yorigin + row * h; + + ri_tile->ri_ops.putchar(ri_tile, 0, screen->ro_curpos, uc, attr); + + gbe_copyrect(gsc, BUF_TYPE_TLB_B, screen->ro_curpos * w, 0, x, y, w, h); + + screen->ro_curpos++; + if ((screen->ro_curpos + 1) * w > screen->ri_tile.ri_width) + screen->ro_curpos = 0; +} + +void +gbe_copycols(void *cookie, int row, int src, int dst, int num) +{ + struct rasops_info *ri = cookie; + struct gbe_softc *sc = ri->ri_hw; + + num *= ri->ri_font->fontwidth; + src *= ri->ri_font->fontwidth; + dst *= ri->ri_font->fontwidth; + row *= ri->ri_font->fontheight; + + gbe_copyrect(sc, BUF_TYPE_TLB_A, ri->ri_xorigin + src, + ri->ri_yorigin + row, ri->ri_xorigin + dst, ri->ri_yorigin + row, + num, ri->ri_font->fontheight); +} + +void +gbe_erasecols(void *cookie, int row, int col, int num, long attr) +{ + struct rasops_info *ri = cookie; + struct gbe_softc *sc = ri->ri_hw; + int bg, fg; + + ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); + + row *= ri->ri_font->fontheight; + col *= ri->ri_font->fontwidth; + num *= ri->ri_font->fontwidth; + + gbe_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, + num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); +} + +void +gbe_copyrows(void *cookie, int src, int dst, int num) +{ + struct rasops_info *ri = cookie; + struct gbe_softc *sc = ri->ri_hw; + + num *= ri->ri_font->fontheight; + src *= ri->ri_font->fontheight; + dst *= ri->ri_font->fontheight; + + gbe_copyrect(sc, BUF_TYPE_TLB_A, ri->ri_xorigin, ri->ri_yorigin + src, + ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); +} + +void +gbe_eraserows(void *cookie, int row, int num, long attr) +{ + struct rasops_info *ri = cookie; + struct gbe_softc *sc = ri->ri_hw; + int x, y, w, bg, fg; + + ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); + + if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { + num = ri->ri_height; + x = y = 0; + w = ri->ri_width; + } else { + num *= ri->ri_font->fontheight; + x = ri->ri_xorigin; + y = ri->ri_yorigin + row * ri->ri_font->fontheight; + w = ri->ri_emuwidth; + } + + gbe_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); +} + +/* * Console functions for early display. */ @@ -852,29 +1279,32 @@ gbe_cnprobe(bus_space_tag_t iot, bus_addr_t addr) int gbe_cnattach(bus_space_tag_t iot, bus_addr_t addr) { - struct gbe_softc gsc; - vaddr_t va; - paddr_t pa; + struct gbe_softc *gsc; uint32_t val; + paddr_t pa; + vaddr_t va; long attr; /* * Setup GBE for use as early console. */ - gsc.curscr = &gbe_consdata; - gbe_consdata.sc = (void *)&gsc; + va = pmap_steal_memory(sizeof(struct gbe_softc), NULL, NULL); + gsc = (struct gbe_softc *)va; + gsc->curscr = &gbe_consdata; + gbe_consdata.sc = (struct device *)gsc; /* Setup bus space mapping. */ - gsc.iot = iot; - gsc.ioh = PHYS_TO_UNCACHED(addr); + gsc->iot = iot; + gsc->ioh = PHYS_TO_UNCACHED(addr); + gsc->re_ioh = PHYS_TO_UNCACHED(RE_BASE); /* Determine GBE revision. */ - gsc.rev = bus_space_read_4(gsc.iot, gsc.ioh, GBE_CTRL_STAT) & 0xf; + gsc->rev = bus_space_read_4(gsc->iot, gsc->ioh, GBE_CTRL_STAT) & 0xf; /* Determine resolution configured by firmware. */ - val = bus_space_read_4(gsc.iot, gsc.ioh, GBE_VT_HCMAP); + val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_HCMAP); gbe_consdata.width = (val >> GBE_VT_HCMAP_ON_SHIFT) & 0xfff; - val = bus_space_read_4(gsc.iot, gsc.ioh, GBE_VT_VCMAP); + val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_VCMAP); gbe_consdata.height = (val >> GBE_VT_VCMAP_ON_SHIFT) & 0xfff; /* Ensure that the firmware has setup the device. */ @@ -903,18 +1333,29 @@ gbe_cnattach(bus_space_tag_t iot, bus_addr_t addr) gbe_consdata.fb_phys = ((pa >> 16) + 1) << 16; gbe_consdata.fb = (caddr_t)PHYS_TO_UNCACHED(gbe_consdata.fb_phys); + /* + * Steal memory for rasops tile - 64KB aligned and coherent. + */ + va = pmap_steal_memory(GBE_TILE_SIZE + 65536, NULL, NULL); + pmap_extract(pmap_kernel(), va, &pa); + gbe_consdata.ro_phys = ((pa >> 16) + 1) << 16; + gbe_consdata.ro = (caddr_t)PHYS_TO_UNCACHED(gbe_consdata.ro_phys); + /* * Setup GBE hardware. */ gbe_init_screen(&gbe_consdata); - gbe_disable(&gsc); - gbe_setup(&gsc); - gbe_enable(&gsc); + gbe_disable(gsc); + gbe_setup(gsc); + gbe_enable(gsc); /* Load colourmap if required. */ if (gbe_consdata.depth == 8) gbe_loadcmap(&gbe_consdata, 0, 255); + /* Clear framebuffer. */ + gbe_fillrect(gsc, 0, 0, gbe_consdata.width, gbe_consdata.height, 0); + /* * Attach wsdisplay. */ diff --git a/sys/arch/sgi/dev/gbereg.h b/sys/arch/sgi/dev/gbereg.h index b75fc7495e3..ef8ff324115 100644 --- a/sys/arch/sgi/dev/gbereg.h +++ b/sys/arch/sgi/dev/gbereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: gbereg.h,v 1.3 2007/12/31 12:46:14 jsing Exp $ */ +/* $OpenBSD: gbereg.h,v 1.4 2009/02/24 14:37:29 jsing Exp $ */ /* * Copyright (c) 2007, Joel Sing <jsing@openbsd.org> @@ -24,14 +24,20 @@ #define GBE_REG_SIZE 0x100000 #define GBE_TLB_SIZE 128 -#define GBE_TILE_SHIFT 16 +#define GBE_TILE_SHIFT 16 #define GBE_TILE_SIZE (1 << GBE_TILE_SHIFT) +#define GBE_TILE_WIDTH 512 /* Width of tile in bytes. */ +#define GBE_TILE_WIDTH_SHIFT 9 +#define GBE_TILE_HEIGHT 128 /* Height of tile in bytes. */ +#define GBE_TILE_HEIGHT_SHIFT 7 + /* - * Register locations. + * GBE Registers. */ #define GBE_CTRL_STAT 0x00000000 /* General control/status */ +#define GBE_CURSOR_ON 0x00000001 #define GBE_DOTCLOCK 0x00000004 /* Dotclock */ #define GBE_DOTCLOCK_RUN 0x00100000 /* Enable dotclock */ #define GBE_VT_XY 0x00010000 /* Current dot coordinates */ @@ -88,7 +94,7 @@ #define GBE_CURSOR_CTRL 0x00070004 /* Cursor control */ /* - * Constants. + * GBE Constants. */ #define GBE_FB_DEPTH_8 0 @@ -107,7 +113,96 @@ #define GBE_BMODE_BOTH 3 /* + * Rendering Engine Registers. + */ + +#define RE_BASE 0x15000000 +#define RE_REG_SIZE 0x5000 +#define RE_START 0x00000800 /* Start rendering operation. */ + +/* TLB Registers. */ +#define RE_TLB_A 0x00001000 /* 256 16-bit tile entries. */ +#define RE_TLB_B 0x00001200 +#define RE_TLB_C 0x00001400 +#define RE_TLB_TEX 0x00001600 +#define RE_TLB_CLIP_ID 0x000016e0 +#define RE_TLB_LINEAR_A 0x00001700 +#define RE_TLB_LINEAR_B 0x00001780 + +/* Pixel Pipeline Registers. */ +#define RE_PP_BUFMODE_SRC 0x00002000 +#define RE_PP_BUFMODE_DST 0x00002008 +#define RE_PP_CLIPMODE 0x00002010 +#define RE_PP_DRAWMODE 0x00002018 +#define DRAWMODE_STENCIL 0x1 << 0 +#define DRAWMODE_DEPTH_MASK 0x1 << 1 +#define DRAWMODE_DEPTH_TEST 0x1 << 2 +#define DRAWMODE_BYTEMASK 0xf << 3 +#define DRAWMODE_BITMASK 0x1 << 7 +#define DRAWMODE_DITHER 0x1 << 8 +#define DRAWMODE_LOGIC_OP 0x1 << 9 +#define DRAWMODE_ALPHA_BLEND 0x1 << 10 +#define DRAWMODE_PIXEL_XFER 0x1 << 21 +#define RE_PP_WINOFFSET_SRC 0x00002050 +#define RE_PP_WINOFFSET_DST 0x00002058 +#define RE_PP_PRIMITIVE 0x00002060 /* Drawing primitive. */ +#define PRIMITIVE_POINT 0x0 << 24 +#define PRIMITIVE_LINE 0x1 << 24 +#define PRIMITIVE_TRIANGLE 0x2 << 24 +#define PRIMITIVE_RECTANGLE 0x3 << 24 +#define PRIMITIVE_LRBT 0x0 << 16 +#define PRIMITIVE_RLBT 0x1 << 16 +#define PRIMITIVE_LRTB 0x2 << 16 +#define PRIMITIVE_RLTB 0x3 << 16 +#define RE_PP_VERTEX_X_0 0x00002070 /* (x0,y0) vertex. */ +#define RE_PP_VERTEX_X_1 0x00002074 /* (x1,y1) vertex. */ +#define RE_PP_VERTEX_X_2 0x00002078 /* (x2,y2) vertex. */ +#define RE_PP_PIXEL_XFER_SRC 0x000020a0 /* Pixel transfer source. */ +#define RE_PP_PIXEL_XFER_X_STEP 0x000020a8 +#define RE_PP_PIXEL_XFER_Y_STEP 0x000020ac +#define RE_PP_STIPPLE_MODE 0x000020c0 +#define RE_PP_STIPPLE_PATTERN 0x000020c4 +#define RE_PP_SHADE_FG_COLOUR 0x000020d0 +#define RE_PP_SHADE_BG_COLOUR 0x000020d8 +#define RE_PP_LOGIC_OP 0x000021b0 /* Logic operation. */ +#define LOGIC_OP_NONE 0x00 +#define LOGIC_OP_XOR 0x0c +#define RE_PP_COLOUR_MASK 0x000021b8 /* Colour buffer plane mask. */ +#define COLOUR_MASK_NONE 0xffffffff +#define RE_PP_NULL 0x000021f0 +#define RE_PP_FLUSH 0x000021f8 + +#define BUFMODE_PIXDEPTH_SHIFT 2 /* Pixel colour depth. */ +#define BUFMODE_PIXTYPE_SHIFT 4 /* Pixel format. */ +#define BUFMODE_BUFDEPTH_SHIFT 8 /* Buffer colour depth. */ +#define BUFMODE_BUFTYPE_SHIFT 10 /* Source or destination. */ + +/* Status Registers. */ +#define RE_PP_STATUS 0x00004000 +#define RE_PP_STATUS_IDLE 0x10000000 +#define RE_PP_STATUS_READY 0x02000000 + +/* + * Rendering Engine Constants. + */ + +#define COLOUR_DEPTH_8 0x0 +#define COLOUR_DEPTH_16 0x1 +#define COLOUR_DEPTH_32 0x2 + +#define PIXEL_TYPE_CI 0x0 +#define PIXEL_TYPE_RGB 0x1 +#define PIXEL_TYPE_RGBA 0x2 +#define PIXEL_TYPE_ABGR 0x3 + +#define BUF_TYPE_TLB_A 0x0 +#define BUF_TYPE_TLB_B 0x1 +#define BUF_TYPE_TLB_C 0x2 +#define BUF_TYPE_LINEAR_A 0x4 +#define BUF_TYPE_LINEAR_B 0x5 + +/* * Console functions. */ -int gbe_cnprobe(bus_space_tag_t, bus_addr_t addr); -int gbe_cnattach(bus_space_tag_t, bus_addr_t addr); +int gbe_cnprobe(bus_space_tag_t, bus_addr_t addr); +int gbe_cnattach(bus_space_tag_t, bus_addr_t addr); |