diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2007-12-31 12:46:15 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2007-12-31 12:46:15 +0000 |
commit | f55c9af49ac20858a1ef9f84f24a11f26bec88ef (patch) | |
tree | aeda19024b7aad741b2158e5dfabbde409ac6292 /sys/arch | |
parent | 5cb6f8c375209885c4063d6b91458743432837a5 (diff) |
Significantly improve the gbe(4) driver, including:
- Internal restructure to separate code paths.
- Add support for early console. This allows for gbe(4) to takeover were
the ARCBios leaves off (if we should do so).
- Add support for 8bpp and 16bpp colour depths. As a result, we also have
support for colourmaps. We now use 8bpp as the default.
- Add mmap() support, enabling wsfb to operate correctly.
- Correct initial origin problem that occurred occasionally.
ok miod@. tested by jasper@.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sgi/conf/files.sgi | 4 | ||||
-rw-r--r-- | sys/arch/sgi/dev/gbe.c | 775 | ||||
-rw-r--r-- | sys/arch/sgi/dev/gbereg.h | 45 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/wscons_machdep.c | 39 |
4 files changed, 636 insertions, 227 deletions
diff --git a/sys/arch/sgi/conf/files.sgi b/sys/arch/sgi/conf/files.sgi index 16e6e00c067..bc321bafa9e 100644 --- a/sys/arch/sgi/conf/files.sgi +++ b/sys/arch/sgi/conf/files.sgi @@ -1,4 +1,4 @@ -# $OpenBSD: files.sgi,v 1.18 2007/12/31 11:42:43 jsing Exp $ +# $OpenBSD: files.sgi,v 1.19 2007/12/31 12:46:14 jsing Exp $ # # maxpartitions must be first item in files.${ARCH} # @@ -87,7 +87,7 @@ file arch/sgi/sgi/clock_md.c clock # GBE framebuffer device gbe: wsemuldisplaydev, rasops8, rasops16, rasops32 attach gbe at mainbus -file arch/sgi/dev/gbe.c gbe +file arch/sgi/dev/gbe.c gbe needs-flag # 16[45]50-based "com" ports on localbus attach com at xbowmux with com_xbow diff --git a/sys/arch/sgi/dev/gbe.c b/sys/arch/sgi/dev/gbe.c index c55304e4c7a..d9939581ee5 100644 --- a/sys/arch/sgi/dev/gbe.c +++ b/sys/arch/sgi/dev/gbe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gbe.c,v 1.3 2007/12/14 16:03:10 jsing Exp $ */ +/* $OpenBSD: gbe.c,v 1.4 2007/12/31 12:46:14 jsing Exp $ */ /* * Copyright (c) 2007, Joel Sing <jsing@openbsd.org> @@ -23,6 +23,9 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/malloc.h> + +#include <uvm/uvm_extern.h> #include <machine/autoconf.h> #include <machine/bus.h> @@ -39,46 +42,77 @@ #include "gbereg.h" -struct gbe_softc { - struct device sc_dev; - struct rasops_info ri; /* Raster display info */ +/* Amount of memory to allocate for framebuffer. */ +#define GBE_FB_SIZE 8 * 1 << 20 - bus_space_tag_t iot; - bus_space_handle_t ioh; +/* + * Colourmap data. + */ +struct gbe_cmap { + u_int8_t cm_red[256]; + u_int8_t cm_green[256]; + u_int8_t cm_blue[256]; +}; - bus_dma_tag_t dmat; +/* + * Screen data. + */ +struct gbe_screen { + struct device *sc; /* Back pointer. */ - bus_dmamap_t tm_dmamap; - bus_dmamap_t fb_dmamap; + struct rasops_info ri; /* Raster display info. */ + struct gbe_cmap cmap; /* Display colour map. */ - bus_dma_segment_t tm_segs[1]; - bus_dma_segment_t fb_segs[1]; + int fb_size; /* Size of framebuffer memory. */ + int tm_size; /* Size of tilemap memory. */ - int tm_nsegs; - int fb_nsegs; + caddr_t tm; /* Address of tilemap memory. */ + paddr_t tm_phys; /* Physical address of tilemap. */ + caddr_t fb; /* Address of framebuffer memory. */ + paddr_t fb_phys; /* Physical address of framebuffer. */ - int fb_size; /* Size of framebuffer memory */ - int tm_size; /* Size of tilemap memory */ + int width; /* Width in pixels. */ + int height; /* Height in pixels. */ + int depth; /* Colour depth in bits. */ + int linebytes; /* Bytes per line. */ +}; - caddr_t tilemap; /* Address of tilemap memory */ - caddr_t fb; /* Address of framebuffer memory */ +/* + * GBE device data. + */ +struct gbe_softc { + struct device sc_dev; + + bus_space_tag_t iot; + bus_space_handle_t ioh; + bus_dma_tag_t dmat; - int rev; /* Revision */ + int rev; /* Hardware revision. */ int console; /* Is this the console? */ - int screens; /* No of screens allocated */ + int screens; /* No of screens allocated. */ - int width; /* Width in pixels */ - int height; /* Height in pixels */ - int depth; /* Colour depth in bits */ - int linebytes; /* Bytes per line */ + struct gbe_screen *curscr; /* Current screen. */ }; +/* + * Hardware and device related functions. + */ +void gbe_init_screen(struct gbe_screen *); +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); + +/* + * Colour map handling for indexed modes. + */ +int gbe_getcmap(struct gbe_cmap *, struct wsdisplay_cmap *); +int gbe_putcmap(struct gbe_cmap *, struct wsdisplay_cmap *); +void gbe_loadcmap(struct gbe_screen *, u_int, u_int); /* * Interfaces for wscons. */ - int gbe_ioctl(void *, u_long, caddr_t, int, struct proc *); paddr_t gbe_mmap(void *, off_t, int); int gbe_alloc_screen(void *, const struct wsscreen_descr *, void **, @@ -88,8 +122,11 @@ int gbe_show_screen(void *, void *, int, void (*)(void *, int, int), void *); void gbe_burner(void *, u_int, u_int); +static struct gbe_screen gbe_consdata; +static int gbe_console; + struct wsscreen_descr gbe_stdscreen = { - "std", /* Screen name */ + "std", /* Screen name. */ }; struct wsdisplay_accessops gbe_accessops = { @@ -138,24 +175,68 @@ void gbe_attach(struct device *parent, struct device *self, void *aux) { struct gbe_softc *gsc = (void*)self; + struct gbe_screen *screen; struct wsemuldisplaydev_attach_args waa; - uint16_t *tm; + bus_dma_segment_t tm_segs[1]; + bus_dma_segment_t fb_segs[1]; + bus_dmamap_t tm_dmamap; + bus_dmamap_t fb_dmamap; + int tm_nsegs; + int fb_nsegs; uint32_t val; long attr; - int i; printf(": "); /* GBE isn't strictly on the crimebus, but use this for now... */ gsc->iot = &crimebus_tag; gsc->dmat = &mace_bus_dma_tag; - gsc->console = 0; + gsc->console = gbe_console; gsc->screens = 0; + if (gsc->console == 1) { + + /* + * We've already been setup via gbe_cnattach(). + */ + + gsc->ioh = PHYS_TO_XKPHYS(GBE_BASE, CCA_NC); + gsc->rev = bus_space_read_4(gsc->iot, gsc->ioh, GBE_CTRL_STAT) + & 0xf; + + gsc->curscr = &gbe_consdata; + gbe_consdata.sc = (void*)self; + + printf("rev %u, %iMB, %dx%d at %d bits\n", gsc->rev, + gbe_consdata.fb_size >> 20, gbe_consdata.width, + gbe_consdata.height, gbe_consdata.depth); + + shutdownhook_establish((void(*)(void *))gbe_disable, self); + + waa.console = gsc->console; + waa.scrdata = &gbe_screenlist; + waa.accessops = &gbe_accessops; + waa.accesscookie = &gbe_consdata; + config_found(self, &waa, wsemuldisplaydevprint); + + return; + } + + /* + * Setup screen data. + */ + gsc->curscr = malloc(sizeof(struct gbe_screen), M_DEVBUF, M_NOWAIT); + if (gsc->curscr == NULL) { + printf("failed to allocate screen memory!\n"); + return; + } + gsc->curscr->sc = (void *)gsc; + screen = gsc->curscr; + /* * Setup bus space mapping. */ - if (bus_space_map(gsc->iot, GBE_BASE - CRIMEBUS_BASE, 0x100000, + 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"); return; @@ -166,49 +247,44 @@ gbe_attach(struct device *parent, struct device *self, void *aux) /* Determine resolution configured by firmware. */ val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_HCMAP); - gsc->width = (val >> GBE_VT_HCMAP_ON_SHIFT) & 0xfff; + screen->width = (val >> GBE_VT_HCMAP_ON_SHIFT) & 0xfff; val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_VCMAP); - gsc->height = (val >> GBE_VT_VCMAP_ON_SHIFT) & 0xfff; + screen->height = (val >> GBE_VT_VCMAP_ON_SHIFT) & 0xfff; - if (gsc->width == 0 || gsc->height == 0) { + if (screen->width == 0 || screen->height == 0) { printf("device has not been setup by firmware!\n"); goto fail0; } - /* Determine colour depth configured by firmware. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE); - gsc->depth = 0x8 << ((val >> GBE_FB_SIZE_TILE_DEPTH_SHIFT) & 0x3); - - /* XXX 8MB and 32bpp for now. */ - gsc->fb_size = 8 * 1024 * 1024; - gsc->tm_size = GBE_TLB_SIZE * sizeof(uint16_t); - gsc->depth = 32; - gsc->linebytes = gsc->width * gsc->depth / 8; + /* Setup screen defaults. */ + screen->fb_size = GBE_FB_SIZE; + screen->tm_size = GBE_TLB_SIZE * sizeof(uint16_t); + screen->depth = 8; + screen->linebytes = screen->width * screen->depth / 8; /* * Setup DMA for tile map. */ - - if (bus_dmamap_create(gsc->dmat, gsc->tm_size, 1, gsc->tm_size, 0, - BUS_DMA_NOWAIT, &gsc->tm_dmamap)) { + 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; } - if (bus_dmamem_alloc(gsc->dmat, gsc->tm_size, 65536, 0, gsc->tm_segs, 1, - &gsc->tm_nsegs, BUS_DMA_NOWAIT)) { + 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; } - if (bus_dmamem_map(gsc->dmat, gsc->tm_segs, gsc->tm_nsegs, gsc->tm_size, - &gsc->tilemap, BUS_DMA_COHERENT)) { + 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; } - if (bus_dmamap_load(gsc->dmat, gsc->tm_dmamap, gsc->tilemap, - gsc->tm_size, NULL, BUS_DMA_NOWAIT)){ + 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; } @@ -216,55 +292,131 @@ gbe_attach(struct device *parent, struct device *self, void *aux) /* * Setup DMA for framebuffer. */ - - if (bus_dmamap_create(gsc->dmat, gsc->fb_size, 1, gsc->fb_size, 0, - BUS_DMA_NOWAIT, &gsc->fb_dmamap)) { + 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; } - if (bus_dmamem_alloc(gsc->dmat, gsc->fb_size, 65536, 0, gsc->fb_segs, - 1, &gsc->fb_nsegs, BUS_DMA_NOWAIT)) { + 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; } - if (bus_dmamem_map(gsc->dmat, gsc->fb_segs, gsc->fb_nsegs, gsc->fb_size, - &gsc->fb, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { + 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; } - if (bus_dmamap_load(gsc->dmat, gsc->fb_dmamap, gsc->fb, gsc->fb_size, + 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; } + screen->tm_phys = tm_dmamap->dm_segs[0].ds_addr; + screen->fb_phys = fb_dmamap->dm_segs[0].ds_addr; + shutdownhook_establish((void(*)(void *))gbe_disable, self); + gbe_init_screen(screen); + gbe_disable(gsc); + gbe_setup(gsc); + gbe_enable(gsc); + + /* Load colourmap if required. */ + if (screen->depth == 8) + gbe_loadcmap(screen, 0, 255); + + printf("rev %u, %iMB, %dx%d at %d bits\n", gsc->rev, + screen->fb_size >> 20, screen->width, screen->height, + screen->depth); + + /* + * Attach wsdisplay. + */ + + /* Attach as console if necessary. */ + if (strncmp(bios_console, "video", 5) == 0) { + screen->ri.ri_ops.alloc_attr(&screen->ri, 0, 0, 0, &attr); + wsdisplay_cnattach(&gbe_stdscreen, &screen->ri, 0, 0, attr); + gsc->console = 1; + } + + waa.console = gsc->console; + waa.scrdata = &gbe_screenlist; + waa.accessops = &gbe_accessops; + waa.accesscookie = screen; + config_found(self, &waa, wsemuldisplaydevprint); + + return; + +fail7: + bus_dmamem_unmap(gsc->dmat, screen->fb, screen->fb_size); +fail6: + bus_dmamem_free(gsc->dmat, fb_segs, fb_nsegs); +fail5: + bus_dmamap_destroy(gsc->dmat, fb_dmamap); +fail4: + bus_dmamap_unload(gsc->dmat, tm_dmamap); +fail3: + bus_dmamem_unmap(gsc->dmat, screen->tm, screen->tm_size); +fail2: + bus_dmamem_free(gsc->dmat, tm_segs, tm_nsegs); +fail1: + bus_dmamap_destroy(gsc->dmat, tm_dmamap); +fail0: + bus_space_unmap(gsc->iot, gsc->ioh, GBE_REG_SIZE); +} + +/* + * GBE hardware specific functions. + */ + +void +gbe_init_screen(struct gbe_screen *screen) +{ + uint16_t *tm; + int i; + /* * Initialise rasops. */ - memset(&gsc->ri, 0, sizeof(struct rasops_info)); - - gsc->ri.ri_flg = RI_CENTER | RI_CLEAR; - gsc->ri.ri_depth = gsc->depth; - gsc->ri.ri_width = gsc->width; - gsc->ri.ri_height = gsc->height; - gsc->ri.ri_bits = (void *)gsc->fb; - gsc->ri.ri_stride = gsc->linebytes; - - if (gsc->depth == 32) { - gsc->ri.ri_rpos = 24; - gsc->ri.ri_rnum = 8; - gsc->ri.ri_gpos = 16; - gsc->ri.ri_gnum = 8; - gsc->ri.ri_bpos = 8; - gsc->ri.ri_bnum = 8; + memset(&screen->ri, 0, sizeof(struct rasops_info)); + + screen->ri.ri_flg = RI_CENTER | RI_CLEAR; + screen->ri.ri_depth = screen->depth; + screen->ri.ri_width = screen->width; + screen->ri.ri_height = screen->height; + screen->ri.ri_bits = (void *)screen->fb; + screen->ri.ri_stride = screen->linebytes; + + if (screen->depth == 32) { + screen->ri.ri_rpos = 24; + screen->ri.ri_rnum = 8; + screen->ri.ri_gpos = 16; + screen->ri.ri_gnum = 8; + screen->ri.ri_bpos = 8; + screen->ri.ri_bnum = 8; + } else if (screen->depth == 16) { + screen->ri.ri_rpos = 10; + screen->ri.ri_rnum = 5; + screen->ri.ri_gpos = 5; + screen->ri.ri_gnum = 5; + screen->ri.ri_bpos = 0; + screen->ri.ri_bnum = 5; } - rasops_init(&gsc->ri, gsc->height / 8, gsc->width / 8); + rasops_init(&screen->ri, screen->height / 8, screen->width / 8); + + gbe_stdscreen.ncols = screen->ri.ri_cols; + gbe_stdscreen.nrows = screen->ri.ri_rows; + gbe_stdscreen.textops = &screen->ri.ri_ops; + gbe_stdscreen.fontwidth = screen->ri.ri_font->fontwidth; + gbe_stdscreen.fontheight = screen->ri.ri_font->fontheight; + gbe_stdscreen.capabilities = screen->ri.ri_caps; /* * Map framebuffer into tile map. Each entry in the tilemap is 16 bits @@ -273,46 +425,130 @@ gbe_attach(struct device *parent, struct device *self, void *aux) * discard the lower 16 bits and store bits 17 through 32 as an entry * in the tilemap. */ - tm = (void *)gsc->tilemap; - for (i = 0; i < (gsc->fb_size >> GBE_TILE_SHIFT); i++) - tm[i] = (gsc->fb_dmamap->dm_segs[0].ds_addr >> GBE_TILE_SHIFT) + i; + tm = (void *)screen->tm; + for (i = 0; i < (screen->fb_size >> GBE_TILE_SHIFT); i++) + tm[i] = (screen->fb_phys >> GBE_TILE_SHIFT) + i; +} + +void +gbe_enable(struct gbe_softc *gsc) +{ + struct gbe_screen *screen = gsc->curscr; + uint32_t val; + int i; + + /* Enable dot clock. */ + val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); + bus_space_write_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK, + val | GBE_DOTCLOCK_RUN); + for (i = 0; i < 10000; i++) { + val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); + if ((val & GBE_DOTCLOCK_RUN) == GBE_DOTCLOCK_RUN) + break; + delay(10); + } + if (i == 10000) + printf("timeout enabling dot clock!\n"); + + /* Unfreeze pixel counter. */ + bus_space_write_4(gsc->iot, gsc->ioh, GBE_VT_XY, 0); + for (i = 0; i < 10000; i++) { + val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY); + if ((val & GBE_VT_XY_FREEZE) == 0) + break; + delay(10); + } + if (i == 10000) + printf("timeout unfreezing pixel counter!\n"); + + /* Provide GBE with address of tile map 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); +} + +void +gbe_disable(struct gbe_softc *gsc) +{ + uint32_t val; + int i; + + /* Nothing to do if the pixel counter is frozen! */ + val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY); + if ((val & GBE_VT_XY_FREEZE) == GBE_VT_XY_FREEZE) + return; + + val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); + if ((val & GBE_DOTCLOCK_RUN) == 0) + return; + + /* Disable overlay and turn off hardware cursor. */ + bus_space_write_4(gsc->iot, gsc->ioh, GBE_OVERLAY_TILE, 0); + bus_space_write_4(gsc->iot, gsc->ioh, GBE_CURSOR_CTRL, 0); + bus_space_write_4(gsc->iot, gsc->ioh, GBE_DID_CTRL, 0); /* Disable DMA. */ val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_OVERLAY_CTRL); bus_space_write_4(gsc->iot, gsc->ioh, GBE_OVERLAY_CTRL, val & ~GBE_OVERLAY_CTRL_DMA_ENABLE); - delay(1000); val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_FB_CTRL); bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_CTRL, val & ~GBE_FB_CTRL_DMA_ENABLE); - delay(1000); bus_space_write_4(gsc->iot, gsc->ioh, GBE_DID_CTRL, 0); - delay(1000); + for (i = 0; i < 100000; i++) { + if ((bus_space_read_4(gsc->iot, gsc->ioh, GBE_OVERLAY_HW_CTRL) + & GBE_OVERLAY_CTRL_DMA_ENABLE) == 0 && + (bus_space_read_4(gsc->iot, gsc->ioh, GBE_FB_HW_CTRL) + & GBE_FB_CTRL_DMA_ENABLE) == 0 && + bus_space_read_4(gsc->iot, gsc->ioh, GBE_DID_HW_CTRL) == 0) + break; + delay(10); + } + if (i == 100000) + printf("timeout disabling DMA!\n"); + + /* Wait for the end of pixel refresh. */ + val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_VPIX) + & GBE_VT_VPIX_OFF_MASK; + for (i = 0; i < 100000; i++) { + if (((bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY) + & GBE_VT_XY_Y_MASK) >> GBE_VT_XY_Y_SHIFT) < val) + break; + delay(1); + } + if (i == 100000) + printf("timeout waiting for pixel refresh!\n"); + for (i = 0; i < 100000; i++) { + if (((bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY) + & GBE_VT_XY_Y_MASK) >> GBE_VT_XY_Y_SHIFT) > val) + break; + delay(1); + } + if (i == 100000) + printf("timeout waiting for pixel refresh!\n"); /* Freeze pixel counter. */ bus_space_write_4(gsc->iot, gsc->ioh, GBE_VT_XY, GBE_VT_XY_FREEZE); - delay(10000); - for (i = 0; i < 10000; i++) { + for (i = 0; i < 100000; i++) { val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY); if ((val & GBE_VT_XY_FREEZE) == GBE_VT_XY_FREEZE) break; delay(10); } - if (i == 10000) + if (i == 100000) printf("timeout freezing pixel counter!\n"); /* Disable dot clock. */ val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); bus_space_write_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK, val & ~GBE_DOTCLOCK_RUN); - delay(10000); - for (i = 0; i < 10000; i++) { + for (i = 0; i < 100000; i++) { val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); if ((val & GBE_DOTCLOCK_RUN) == 0) break; delay(10); } - if (i == 10000) + if (i == 100000) printf("timeout disabling dot clock!\n"); /* Reset DMA fifo. */ @@ -321,115 +557,71 @@ gbe_attach(struct device *parent, struct device *self, void *aux) bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, val | (1 << GBE_FB_SIZE_TILE_FIFO_RESET_SHIFT)); bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, val); +} - /* Disable overlay and turn off hardware cursor. */ - bus_space_write_4(gsc->iot, gsc->ioh, GBE_OVERLAY_TILE, 0); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_CURSOR_CTRL, 0); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_DID_CTRL, 0); +void +gbe_setup(struct gbe_softc *gsc) +{ + struct gbe_screen *screen = gsc->curscr; + uint32_t val; + int i, cmode; + u_char *colour; + + /* + * Setup framebuffer. + */ + switch (screen->depth) { + case 32: + cmode = GBE_CMODE_RGB8; + break; + case 16: + cmode = GBE_CMODE_ARGB5; + break; + case 8: + default: + cmode = GBE_CMODE_I8; + break; + } /* Trick framebuffer into linear mode. */ - i = gsc->width * gsc->height / (512 / (gsc->depth >> 3)); + 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); - /* Setup framebuffer - fixed at 32bpp for now. */ bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, (1 << GBE_FB_SIZE_TILE_WIDTH_SHIFT) | - (GBE_FB_DEPTH_32 << GBE_FB_SIZE_TILE_DEPTH_SHIFT)); - val = (GBE_CMODE_RGB8 << GBE_WID_MODE_SHIFT) | GBE_BMODE_BOTH; + ((screen->depth >> 4) << GBE_FB_SIZE_TILE_DEPTH_SHIFT)); + + 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); - /* Enable dot clock. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK, - val | GBE_DOTCLOCK_RUN); - delay(10000); - for (i = 0; i < 10000; i++) { - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); - if ((val & GBE_DOTCLOCK_RUN) == GBE_DOTCLOCK_RUN) - break; - delay(10); - } - if (i == 10000) - printf("timeout enabling dot clock!\n"); - - /* Unfreeze pixel counter. */ - bus_space_write_4(gsc->iot, gsc->ioh, GBE_VT_XY, 0); - delay(10000); - for (i = 0; i < 10000; i++) { - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY); - if ((val & GBE_VT_XY_FREEZE) == 0) - break; - delay(10); - } - if (i == 10000) - printf("timeout unfreezing pixel counter!\n"); - - /* Provide GBE with address of tile map and enable DMA. */ - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_CTRL, - ((gsc->tm_dmamap->dm_segs[0].ds_addr >> 9) << - GBE_FB_CTRL_TILE_PTR_SHIFT) | GBE_FB_CTRL_DMA_ENABLE); - - printf("rev %u, %iMB, %dx%d at %d bits\n", gsc->rev, gsc->fb_size >> 20, - gsc->width, gsc->height, gsc->depth); - /* - * Setup default screen and attach wsdisplay. + * Initialise colourmap if required. */ - - gbe_stdscreen.ncols = gsc->ri.ri_cols; - gbe_stdscreen.nrows = gsc->ri.ri_rows; - gbe_stdscreen.textops = &gsc->ri.ri_ops; - gbe_stdscreen.fontwidth = gsc->ri.ri_font->fontwidth; - gbe_stdscreen.fontheight = gsc->ri.ri_font->fontheight; - gbe_stdscreen.capabilities = gsc->ri.ri_caps; - - /* Attach as console if necessary. */ - if (strncmp(bios_console, "video", 5) == 0) { - gsc->ri.ri_ops.alloc_attr(&gsc->ri, 0, 0, 0, &attr); - wsdisplay_cnattach(&gbe_stdscreen, &gsc->ri, 0, 0, attr); - gsc->console = 1; + if (screen->depth == 8) { + for (i = 0; i < 16; i++) { + colour = (u_char *)&rasops_cmap[i * 3]; + screen->cmap.cm_red[i] = colour[0]; + screen->cmap.cm_green[i] = colour[1]; + screen->cmap.cm_blue[i] = colour[2]; + } + for (i = 240; i < 256; i++) { + colour = (u_char *)&rasops_cmap[i * 3]; + screen->cmap.cm_red[i] = colour[0]; + screen->cmap.cm_green[i] = colour[1]; + screen->cmap.cm_blue[i] = colour[2]; + } } - waa.console = gsc->console; - waa.scrdata = &gbe_screenlist; - waa.accessops = &gbe_accessops; - waa.accesscookie = self; - config_found(self, &waa, wsemuldisplaydevprint); - - return; + /* + * Setup an alpha ramp. + */ + for (i = 0; i < GBE_GMAP_ENTRIES; i++) + bus_space_write_4(gsc->iot, gsc->ioh, + GBE_GMAP + i * sizeof(u_int32_t), + (i << 24) | (i << 16) | (i << 8)); -fail7: - bus_dmamem_unmap(gsc->dmat, gsc->fb, gsc->fb_size); -fail6: - bus_dmamem_free(gsc->dmat, gsc->fb_segs, gsc->fb_nsegs); -fail5: - bus_dmamap_destroy(gsc->dmat, gsc->fb_dmamap); -fail4: - bus_dmamap_unload(gsc->dmat, gsc->tm_dmamap); -fail3: - bus_dmamem_unmap(gsc->dmat, gsc->tilemap, gsc->tm_size); -fail2: - bus_dmamem_free(gsc->dmat, gsc->tm_segs, gsc->tm_nsegs); -fail1: - bus_dmamap_destroy(gsc->dmat, gsc->tm_dmamap); -fail0: - bus_space_unmap(gsc->iot, gsc->ioh, 0x100000); -} - -/* - * GBE hardware specific functions. - */ - -void -gbe_disable(struct gbe_softc *gsc) -{ - uint32_t val; - - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_FB_CTRL); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_CTRL, - val & ~GBE_FB_CTRL_DMA_ENABLE); } /* @@ -439,7 +631,8 @@ gbe_disable(struct gbe_softc *gsc) int gbe_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) { - struct gbe_softc *gsc = (struct gbe_softc *)v; + struct gbe_screen *screen = (struct gbe_screen *)v; + int rc; switch (cmd) { case WSDISPLAYIO_GTYPE: @@ -450,41 +643,37 @@ gbe_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) { struct wsdisplay_fbinfo *fb = (struct wsdisplay_fbinfo *)data; - fb->height = gsc->height; - fb->width = gsc->width; - fb->depth = gsc->depth; - fb->cmsize = gsc->depth == 8 ? 256 : 0; + fb->height = screen->height; + fb->width = screen->width; + fb->depth = screen->depth; + fb->cmsize = screen->depth == 8 ? 256 : 0; } break; case WSDISPLAYIO_LINEBYTES: - *(u_int *)data = gsc->linebytes; + *(u_int *)data = screen->linebytes; break; case WSDISPLAYIO_GETCMAP: - if (gsc->depth == 8) { -#ifdef notyet + if (screen->depth == 8) { struct wsdisplay_cmap *cm = (struct wsdisplay_cmap *)data; - rc = gbe_getcmap(&scr->scr_cmap, cm); + rc = gbe_getcmap(&screen->cmap, cm); if (rc != 0) return (rc); -#endif } break; case WSDISPLAYIO_PUTCMAP: - if (gsc->depth == 8) { -#ifdef notyet + if (screen->depth == 8) { struct wsdisplay_cmap *cm = (struct wsdisplay_cmap *)data; - rc = gbe_putcmap(&scr->scr_cmap, cm); + rc = gbe_putcmap(&screen->cmap, cm); if (rc != 0) return (rc); - gbe_loadcmap(sc, cm->index, cm->index + cm->count); -#endif + gbe_loadcmap(screen, cm->index, cm->index + cm->count); } break; @@ -503,15 +692,23 @@ gbe_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) paddr_t gbe_mmap(void *v, off_t offset, int protection) { - /* Not at the moment. */ - return (-1); + struct gbe_screen *screen = (void *)v; + paddr_t pa; + + if (offset >= 0 && offset < screen->fb_size) + pa = atop(screen->fb_phys + offset); + else + pa = -1; + + return (pa); } int gbe_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, int *curxp, int *curyp, long *attrp) { - struct gbe_softc *gsc = (struct gbe_softc *)v; + struct gbe_screen *screen = (struct gbe_screen *)v; + struct gbe_softc *gsc = (struct gbe_softc *)screen->sc; /* We do not allow multiple consoles at the moment. */ if (gsc->screens > 0) @@ -520,16 +717,16 @@ gbe_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, gsc->screens++; /* Return rasops_info via cookie. */ - *cookiep = &gsc->ri; + *cookiep = &screen->ri; /* Move cursor to top left of screen. */ *curxp = 0; *curyp = 0; /* Correct screen attributes. */ - gsc->ri.ri_ops.alloc_attr(&gsc->ri, 0, 0, 0, attrp); + screen->ri.ri_ops.alloc_attr(&screen->ri, 0, 0, 0, attrp); - return 0; + return (0); } void @@ -550,3 +747,179 @@ void gbe_burner(void *v, u_int on, u_int flags) { } + +/* + * Colour map handling for indexed modes. + */ + +void +gbe_setcolour(struct gbe_softc *gsc, u_int index, u_int8_t r, u_int8_t g, + u_int8_t b) +{ + int i; + + /* Wait until the colourmap FIFO has free space. */ + for (i = 0; i < 10000; i++) { + if (bus_space_read_4(gsc->iot, gsc->ioh, GBE_CMAP_FIFO) + < GBE_CMAP_FIFO_ENTRIES) + break; + delay(10); + } + if (i == 10000) + printf("colourmap FIFO has no free space!\n"); + + bus_space_write_4(gsc->iot, gsc->ioh, + GBE_CMAP + index * sizeof(u_int32_t), + ((u_int)r << 24) | ((u_int)g << 16) | ((u_int)b << 8)); +} + +int +gbe_getcmap(struct gbe_cmap *cm, struct wsdisplay_cmap *rcm) +{ + u_int index = rcm->index, count = rcm->count; + int rc; + + if (index >= 256 || count > 256 - index) + return (EINVAL); + + if ((rc = copyout(&cm->cm_red[index], rcm->red, count)) != 0) + return (rc); + if ((rc = copyout(&cm->cm_green[index], rcm->green, count)) != 0) + return (rc); + if ((rc = copyout(&cm->cm_blue[index], rcm->blue, count)) != 0) + return (rc); + + return (0); +} + +int +gbe_putcmap(struct gbe_cmap *cm, struct wsdisplay_cmap *rcm) +{ + u_int index = rcm->index, count = rcm->count; + int rc; + + if (index >= 256 || count > 256 - index) + return (EINVAL); + + if ((rc = copyin(rcm->red, &cm->cm_red[index], count)) != 0) + return (rc); + if ((rc = copyin(rcm->green, &cm->cm_green[index], count)) != 0) + return (rc); + if ((rc = copyin(rcm->blue, &cm->cm_blue[index], count)) != 0) + return (rc); + + return (0); +} + +void +gbe_loadcmap(struct gbe_screen *screen, u_int start, u_int end) +{ + struct gbe_softc *gsc = (void *)screen->sc; + struct gbe_cmap *cm = &screen->cmap; + + for (; start <= end; start++) + gbe_setcolour(gsc, start, + cm->cm_red[start], cm->cm_green[start], cm->cm_blue[start]); +} + +/* + * Console functions for early display. + */ + +int +gbe_cnprobe(bus_space_tag_t iot, bus_addr_t addr) +{ + bus_space_handle_t ioh; + int val, width, height; + + /* Setup bus space mapping. */ + ioh = PHYS_TO_XKPHYS(addr, CCA_NC); + + /* Determine resolution configured by firmware. */ + val = bus_space_read_4(iot, ioh, GBE_VT_HCMAP); + width = (val >> GBE_VT_HCMAP_ON_SHIFT) & 0xfff; + val = bus_space_read_4(iot, ioh, GBE_VT_VCMAP); + height = (val >> GBE_VT_VCMAP_ON_SHIFT) & 0xfff; + + /* Ensure that the firmware has setup the device. */ + if (width != 0 && height != 0) + return (1); + else + return (0); +} + +int +gbe_cnattach(bus_space_tag_t iot, bus_addr_t addr) +{ + struct gbe_softc gsc; + vaddr_t va; + paddr_t pa; + uint32_t val; + long attr; + + /* + * Setup GBE for use as early console. + */ + gsc.curscr = &gbe_consdata; + gbe_consdata.sc = (void *)&gsc; + + /* Setup bus space mapping. */ + gsc.iot = iot; + gsc.ioh = PHYS_TO_XKPHYS(addr, CCA_NC); + + /* Determine GBE revision. */ + 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); + gbe_consdata.width = (val >> GBE_VT_HCMAP_ON_SHIFT) & 0xfff; + 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. */ + if (gbe_consdata.width == 0 || gbe_consdata.height == 0) + return (ENXIO); + + /* Setup screen defaults. */ + gbe_consdata.fb_size = GBE_FB_SIZE; + gbe_consdata.tm_size = GBE_TLB_SIZE * sizeof(uint16_t); + gbe_consdata.depth = 8; + gbe_consdata.linebytes = gbe_consdata.width * gbe_consdata.depth / 8; + + /* + * Steal memory for tilemap - 64KB aligned and coherent. + */ + va = pmap_steal_memory(gbe_consdata.tm_size + 65536, NULL, NULL); + pmap_extract(pmap_kernel(), va, &pa); + gbe_consdata.tm_phys = ((pa >> 16) + 1) << 16; + gbe_consdata.tm = (caddr_t)PHYS_TO_XKPHYS(gbe_consdata.tm_phys, CCA_NC); + + /* + * Steal memory for framebuffer - 64KB aligned and coherent. + */ + va = pmap_steal_memory(gbe_consdata.fb_size + 65536, NULL, NULL); + pmap_extract(pmap_kernel(), va, &pa); + gbe_consdata.fb_phys = ((pa >> 16) + 1) << 16; + gbe_consdata.fb = (caddr_t)PHYS_TO_XKPHYS(gbe_consdata.fb_phys, CCA_NC); + + /* + * Setup GBE hardware. + */ + gbe_init_screen(&gbe_consdata); + gbe_disable(&gsc); + gbe_setup(&gsc); + gbe_enable(&gsc); + + /* Load colourmap if required. */ + if (gbe_consdata.depth == 8) + gbe_loadcmap(&gbe_consdata, 0, 255); + + /* + * Attach wsdisplay. + */ + gbe_consdata.ri.ri_ops.alloc_attr(&gbe_consdata.ri, 0, 0, 0, &attr); + wsdisplay_cnattach(&gbe_stdscreen, &gbe_consdata.ri, 0, 0, attr); + gbe_console = 1; + + return (1); +} diff --git a/sys/arch/sgi/dev/gbereg.h b/sys/arch/sgi/dev/gbereg.h index 312e908ae02..b75fc7495e3 100644 --- a/sys/arch/sgi/dev/gbereg.h +++ b/sys/arch/sgi/dev/gbereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: gbereg.h,v 1.2 2007/11/27 16:08:06 jasper Exp $ */ +/* $OpenBSD: gbereg.h,v 1.3 2007/12/31 12:46:14 jsing Exp $ */ /* * Copyright (c) 2007, Joel Sing <jsing@openbsd.org> @@ -21,6 +21,7 @@ */ #define GBE_BASE 0x16000000 +#define GBE_REG_SIZE 0x100000 #define GBE_TLB_SIZE 128 #define GBE_TILE_SHIFT 16 @@ -34,6 +35,10 @@ #define GBE_DOTCLOCK 0x00000004 /* Dotclock */ #define GBE_DOTCLOCK_RUN 0x00100000 /* Enable dotclock */ #define GBE_VT_XY 0x00010000 /* Current dot coordinates */ +#define GBE_VT_XY_X_SHIFT 0 +#define GBE_VT_XY_X_MASK 0x00000fff +#define GBE_VT_XY_Y_SHIFT 12 +#define GBE_VT_XY_Y_MASK 0x00fff000 #define GBE_VT_XY_FREEZE 0x80000000 /* Freeze pixel counter */ #define GBE_VT_MAXXY 0x00010004 /* */ #define GBE_VT_VSYNC 0x00010008 /* Vertical sync on/off */ @@ -42,8 +47,12 @@ #define GBE_VT_HBLANK 0x00010014 /* Horizontal blanking */ #define GBE_VT_FLAGS 0x00010018 /* Video timing flags */ #define GBE_VT_SYNC_LOW 0x00000010 /* Sync on green */ -#define GBE_VT_HPIXEN 0x00010034 /* Horizontal pixel on/off */ -#define GBE_VT_VPIXEN 0x00010038 /* Vertical pixel on/off */ +#define GBE_VT_HPIX 0x00010034 /* Horizontal pixel on/off */ +#define GBE_VT_VPIX 0x00010038 /* Vertical pixel on/off */ +#define GBE_VT_VPIX_OFF_MASK 0x00000fff +#define GBE_VT_VPIX_OFF_SHIFT 0 +#define GBE_VT_VPIX_ON_MASK 0x00fff000 +#define GBE_VT_VPIX_ON_SHIFT 12 #define GBE_VT_HCMAP 0x0001003c /* Horizontal cmap write */ #define GBE_VT_HCMAP_ON_SHIFT 12 #define GBE_VT_VCMAP 0x00010040 /* Vertical cmap write */ @@ -61,12 +70,20 @@ #define GBE_FB_SIZE_TILE_FIFO_RESET_SHIFT 15 #define GBE_FB_SIZE_PIXEL 0x00030004 /* Framebuffer - pixel size */ #define GBE_FB_SIZE_PIXEL_HEIGHT_SHIFT 16 +#define GBE_FB_HW_CTRL 0x00030008 /* Framebuffer - hardware control */ #define GBE_FB_CTRL 0x0003000c /* Framebuffer - control */ #define GBE_FB_CTRL_TILE_PTR_SHIFT 9 #define GBE_FB_CTRL_DMA_ENABLE 0x00000001 +#define GBE_DID_HW_CTRL 0x00040000 /* DID hardware control */ #define GBE_DID_CTRL 0x00040004 /* DID control */ #define GBE_MODE 0x00048000 /* Colour mode */ #define GBE_WID_MODE_SHIFT 2 +#define GBE_CMAP 0x050000 /* Colourmap */ +#define GBE_CMAP_ENTRIES 6144 +#define GBE_CMAP_FIFO 0x058000 /* Colourmap FIFO status */ +#define GBE_CMAP_FIFO_ENTRIES 63 +#define GBE_GMAP 0x060000 /* Gammamap */ +#define GBE_GMAP_ENTRIES 256 #define GBE_CURSOR_POS 0x00070000 /* Cursor position */ #define GBE_CURSOR_CTRL 0x00070004 /* Cursor control */ @@ -78,13 +95,19 @@ #define GBE_FB_DEPTH_16 1 #define GBE_FB_DEPTH_32 2 -#define GBE_CMODE_I8 0 -#define GBE_CMODE_I12 1 -#define GBE_CMODE_RG3B2 2 -#define GBE_CMODE_RGB4 3 -#define GBE_CMODE_ARGB5 4 -#define GBE_CMODE_RGB8 5 -#define GBE_CMODE_RGBA5 6 -#define GBE_CMODE_RGB10 7 +#define GBE_CMODE_I8 0 /* 8 bit indexed */ +#define GBE_CMODE_I12 1 /* 12 bit indexed */ +#define GBE_CMODE_RG3B2 2 /* 3:3:2 direct */ +#define GBE_CMODE_RGB4 3 /* 4:4:4 direct */ +#define GBE_CMODE_ARGB5 4 /* 1:5:5:5 direct */ +#define GBE_CMODE_RGB8 5 /* 8:8:8 direct */ +#define GBE_CMODE_RGBA5 6 /* 5:5:5:5 direct */ +#define GBE_CMODE_RGB10 7 /* 10:10:10 direct */ #define GBE_BMODE_BOTH 3 + +/* + * Console functions. + */ +int gbe_cnprobe(bus_space_tag_t, bus_addr_t addr); +int gbe_cnattach(bus_space_tag_t, bus_addr_t addr); diff --git a/sys/arch/sgi/sgi/wscons_machdep.c b/sys/arch/sgi/sgi/wscons_machdep.c index 43e9acfb6dd..ebe0b187aa8 100644 --- a/sys/arch/sgi/sgi/wscons_machdep.c +++ b/sys/arch/sgi/sgi/wscons_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wscons_machdep.c,v 1.1 2007/12/31 11:42:43 jsing Exp $ */ +/* $OpenBSD: wscons_machdep.c,v 1.2 2007/12/31 12:46:14 jsing Exp $ */ /* * Copyright (c) 2001 Aaron Campbell @@ -37,16 +37,21 @@ #include <machine/bus.h> #include <mips64/arcbios.h> +#include <mips64/archtype.h> -#include <sgi/dev/mkbcreg.h> +#include <sgi/localbus/crimebus.h> #include <sgi/localbus/macebus.h> +#include <sgi/dev/gbereg.h> +#include <sgi/dev/mkbcreg.h> + #include <dev/cons.h> #include <dev/ic/pckbcvar.h> #include <dev/usb/ukbdvar.h> #include <dev/wscons/wskbdvar.h> #include <dev/wscons/wsconsio.h> +#include "gbe.h" #include "mkbc.h" #include "wsdisplay.h" @@ -73,12 +78,21 @@ wscnprobe(struct consdev *cp) } cp->cn_dev = makedev(maj, 0); - - /* Attach as console if necessary. */ - if (strncmp(bios_console, "video", 5) == 0) { - cp->cn_pri = CN_REMOTE; - } else { - cp->cn_pri = CN_INTERNAL; + cp->cn_pri = CN_DEAD; + + switch (sys_config.system_type) { + case SGI_O2: +#if NGBE > 0 + if (gbe_cnprobe(&crimebus_tag, GBE_BASE)) { + if (strncmp(bios_console, "video", 5) == 0) + cp->cn_pri = CN_FORCED; + else + cp->cn_pri = CN_INTERNAL; + } +#endif + break; + default: + break; } } @@ -92,15 +106,14 @@ static int initted; initted = 1; +#if NGBE > 0 + if (!gbe_cnattach(&crimebus_tag, GBE_BASE)) + return; +#endif #if NMKBC > 0 if (!mkbc_cnattach(&macebus_tag, 0x00320000, PCKBC_KBD_SLOT)) return; #endif -#if notyet - ukbd_cnattach(); -#endif - - return; } void |