diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2010-03-04 14:50:36 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2010-03-04 14:50:36 +0000 |
commit | 362b413ed4f676c5cb0c69ebaac4fca2acafb315 (patch) | |
tree | 776b85fc168b29aeae3e55a88a1afec837eafe87 | |
parent | 6c7b46ab88c086928bfcbd0bd0c184cfb4273dca (diff) |
Introduce odyssey(4), a driver for the SGI VPro (aka Odyssey) graphics
card, which can be found in Octane, Octane2, Fuel, Tezro and Onyx systems.
ok miod@
-rw-r--r-- | share/man/man4/man4.sgi/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/man4.sgi/odyssey.4 | 55 | ||||
-rw-r--r-- | sys/arch/sgi/conf/GENERIC-IP27 | 4 | ||||
-rw-r--r-- | sys/arch/sgi/conf/GENERIC-IP30 | 4 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/files.xbow | 8 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/odyssey.c | 1048 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/odysseyreg.h | 62 |
7 files changed, 1180 insertions, 5 deletions
diff --git a/share/man/man4/man4.sgi/Makefile b/share/man/man4/man4.sgi/Makefile index 4324cb39131..8920c2f758a 100644 --- a/share/man/man4/man4.sgi/Makefile +++ b/share/man/man4/man4.sgi/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.16 2009/11/10 17:08:06 miod Exp $ +# $OpenBSD: Makefile,v 1.17 2010/03/04 14:50:35 jsing Exp $ MAN= dsrtc.4 gbe.4 iec.4 intro.4 ioc.4 iockbc.4 iof.4 \ - macebus.4 mavb.4 mec.4 mkbc.4 \ + macebus.4 mavb.4 mec.4 mkbc.4 odyssey.4 \ owmac.4 owserial.4 power.4 xbow.4 xbridge.4 xheart.4 MLINKS= macebus.4 macepcibr.4 \ xbridge.4 xbpci.4 diff --git a/share/man/man4/man4.sgi/odyssey.4 b/share/man/man4/man4.sgi/odyssey.4 new file mode 100644 index 00000000000..33783b40d5f --- /dev/null +++ b/share/man/man4/man4.sgi/odyssey.4 @@ -0,0 +1,55 @@ +.\" $OpenBSD: odyssey.4,v 1.1 2010/03/04 14:50:35 jsing Exp $ +.\" +.\" Copyright (c) 2010 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 +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: March 4 2010 $ +.Dt ODYSSEY 4 sgi +.Os +.Sh NAME +.Nm odyssey +.Nd SGI VPro (aka Odyssey) graphics card driver +.Sh SYNOPSIS +.Cd "odyssey* at xbow?" +.Cd "wsdisplay* at odyssey?" +.Sh DESCRIPTION +The +.Nm +driver provides support for the VPro (aka Odyssey) graphics card, which can be +found in SGI +.Tn Octane , +.Tn Octane2 , +.Tn Fuel , +.Tn Tezro +and +.Tn Onyx +systems. +Console support is provided by the +.Xr wscons 4 +console framework. +.Sh SEE ALSO +.Xr intro 4 , +.Xr wscons 4 , +.Xr wsdisplay 4 , +.Xr xbow 4 +.Sh HISTORY +The +.Nm +driver first appeared in +.Ox 4.7 . +.Sh AUTHORS +The +.Nm +driver was written by +.An Joel Sing . diff --git a/sys/arch/sgi/conf/GENERIC-IP27 b/sys/arch/sgi/conf/GENERIC-IP27 index 4581bfe74b9..ec5bb27e55f 100644 --- a/sys/arch/sgi/conf/GENERIC-IP27 +++ b/sys/arch/sgi/conf/GENERIC-IP27 @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC-IP27,v 1.29 2010/02/01 22:06:27 jasper Exp $ +# $OpenBSD: GENERIC-IP27,v 1.30 2010/03/04 14:50:35 jsing Exp $ # # THIS KERNEL IS FOR Origin, Onyx, Fuel, Tezro (IP27, IP35) SYSTEMS ONLY. # @@ -47,6 +47,8 @@ xbow* at mainbus0 xbridge* at xbow? xbpci* at xbridge? pci* at xbpci? +odyssey* at xbow? +wsdisplay* at odyssey? # IOC3 ioc* at pci? diff --git a/sys/arch/sgi/conf/GENERIC-IP30 b/sys/arch/sgi/conf/GENERIC-IP30 index fc0d763c3e3..34c1c7da3b8 100644 --- a/sys/arch/sgi/conf/GENERIC-IP30 +++ b/sys/arch/sgi/conf/GENERIC-IP30 @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC-IP30,v 1.24 2010/02/01 22:06:27 jasper Exp $ +# $OpenBSD: GENERIC-IP30,v 1.25 2010/03/04 14:50:35 jsing Exp $ # # THIS KERNEL IS FOR Octane and Octane 2 (IP30) SYSTEMS ONLY. # @@ -50,6 +50,8 @@ onewire* at xheart? xbridge* at xbow? xbpci* at xbridge? pci* at xbpci? +odyssey* at xbow? +wsdisplay* at odyssey? # IOC3 ioc* at pci? diff --git a/sys/arch/sgi/xbow/files.xbow b/sys/arch/sgi/xbow/files.xbow index 7287b097dfa..fb6d8d13590 100644 --- a/sys/arch/sgi/xbow/files.xbow +++ b/sys/arch/sgi/xbow/files.xbow @@ -1,4 +1,4 @@ -# $OpenBSD: files.xbow,v 1.5 2009/10/22 19:55:45 miod Exp $ +# $OpenBSD: files.xbow,v 1.6 2010/03/04 14:50:35 jsing Exp $ # IP30 and IP27 planar XBow bus define xbow {[widget = -1], [vendor = -1], [product = -1]} @@ -17,3 +17,9 @@ attach xbridge at xbow device xbpci {[bus = -1]} : pcibus attach xbpci at xbridge file arch/sgi/xbow/xbridge.c xbridge + +# Odyssey graphics +device odyssey: wsemuldisplaydev, rasops8, rasops16, rasops32 +attach odyssey at xbow +file arch/sgi/xbow/odyssey.c odyssey needs-flag + diff --git a/sys/arch/sgi/xbow/odyssey.c b/sys/arch/sgi/xbow/odyssey.c new file mode 100644 index 00000000000..b7cc082de55 --- /dev/null +++ b/sys/arch/sgi/xbow/odyssey.c @@ -0,0 +1,1048 @@ +/* $OpenBSD: odyssey.c,v 1.1 2010/03/04 14:50:35 jsing Exp $ */ +/* + * Copyright (c) 2009, 2010 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Driver for the SGI VPro (aka Odyssey) Graphics Card. + */ + +/* + * The details regarding the design and operation of this hardware, along with + * the necessary magic numbers, are only available thanks to the reverse + * engineering work undertaken by Stanislaw Skowronek <skylark@linux-mips.org>. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/types.h> +#include <sys/malloc.h> + +#include <machine/autoconf.h> + +#include <mips64/arcbios.h> + +#include <sgi/xbow/xbow.h> +#include <sgi/xbow/xbowdevs.h> +#include <sgi/xbow/odysseyreg.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsdisplayvar.h> +#include <dev/rasops/rasops.h> + +/* + * Colourmap data. + */ +struct odyssey_cmap { + u_int8_t cm_red[256]; + u_int8_t cm_green[256]; + u_int8_t cm_blue[256]; +}; + +/* + * Screen data. + */ +struct odyssey_screen { + struct device *sc; /* Back pointer. */ + + struct rasops_info ri; /* Screen raster display info. */ + struct odyssey_cmap cmap; /* Display colour map. */ + long attr; /* Rasops attributes. */ + + int width; /* Width in pixels. */ + int height; /* Height in pixels. */ + int depth; /* Colour depth in bits. */ + int linebytes; /* Bytes per line. */ + int ro_curpos; /* Current position in rasops tile. */ +}; + +struct odyssey_softc { + struct device sc_dev; + + struct mips_bus_space iot_store; + bus_space_tag_t iot; + bus_space_handle_t ioh; + + int console; /* Is this the console? */ + int screens; /* No of screens allocated. */ + + struct odyssey_screen *curscr; /* Current screen. */ +}; + +int odyssey_match(struct device *, void *, void *); +void odyssey_attach(struct device *, struct device *, void *); + +void odyssey_cmd_wait(struct odyssey_softc *); +void odyssey_data_wait(struct odyssey_softc *); +void odyssey_cmd_flush(struct odyssey_softc *, int); + +void odyssey_setup(struct odyssey_softc *); +void odyssey_init_screen(struct odyssey_screen *); + +/* + * Colour map handling for indexed modes. + */ +int odyssey_getcmap(struct odyssey_cmap *, struct wsdisplay_cmap *); +int odyssey_putcmap(struct odyssey_cmap *, struct wsdisplay_cmap *); + +/* + * Hardware acceleration for rasops. + */ +void odyssey_rop(struct odyssey_softc *, int, int, int, int, int, int); +void odyssey_copyrect(struct odyssey_softc *, int, int, int, int, int, int); +void odyssey_fillrect(struct odyssey_softc *, int, int, int, int, u_int); +int odyssey_do_cursor(struct rasops_info *); +int odyssey_putchar(void *, int, int, u_int, long); +int odyssey_copycols(void *, int, int, int, int); +int odyssey_erasecols(void *, int, int, int, long); +int odyssey_copyrows(void *, int, int, int); +int odyssey_eraserows(void *, int, int, long); + +u_int32_t ieee754_sp(int32_t); + +/* + * Interfaces for wscons. + */ +int odyssey_ioctl(void *, u_long, caddr_t, int, struct proc *); +paddr_t odyssey_mmap(void *, off_t, int); +int odyssey_alloc_screen(void *, const struct wsscreen_descr *, void **, + int *, int *, long *); +void odyssey_free_screen(void *, void *); +int odyssey_show_screen(void *, void *, int, void (*)(void *, int, int), + void *); +void odyssey_burner(void *, u_int, u_int); + +struct wsscreen_descr odyssey_stdscreen = { + "std", /* Screen name. */ +}; + +struct wsdisplay_accessops odyssey_accessops = { + odyssey_ioctl, + odyssey_mmap, + odyssey_alloc_screen, + odyssey_free_screen, + odyssey_show_screen, + NULL, /* load_font */ + NULL, /* scrollback */ + NULL, /* getchar */ + odyssey_burner, + NULL /* pollc */ +}; + +const struct wsscreen_descr *odyssey_scrlist[] = { + &odyssey_stdscreen +}; + +struct wsscreen_list odyssey_screenlist = { + nitems(odyssey_scrlist), odyssey_scrlist +}; + +const struct cfattach odyssey_ca = { + sizeof(struct odyssey_softc), odyssey_match, odyssey_attach, +}; + +struct cfdriver odyssey_cd = { + NULL, "odyssey", DV_DULL, +}; + +int +odyssey_match(struct device *parent, void *match, void *aux) +{ + struct xbow_attach_args *xaa = aux; + + if (xaa->xaa_vendor == XBOW_VENDOR_SGI2 && + xaa->xaa_product == XBOW_PRODUCT_SGI2_ODYSSEY) + return 1; + + return 0; +} + +void +odyssey_attach(struct device *parent, struct device *self, void *aux) +{ + struct xbow_attach_args *xaa = aux; + struct wsemuldisplaydev_attach_args waa; + struct odyssey_softc *sc = (void *)self; + struct odyssey_screen *screen; + + if (strncmp(bios_graphics, "alive", 5) != 0) { + printf(" device has not been setup by firmware!\n"); + return; + } + + printf(" revision %d\n", xaa->xaa_revision); + + /* + * Create a copy of the bus space tag. + */ + bcopy(xaa->xaa_iot, &sc->iot_store, sizeof(struct mips_bus_space)); + sc->iot = &sc->iot_store; + + /* + * Setup screen data. + */ + sc->curscr = malloc(sizeof(struct odyssey_screen), M_DEVBUF, M_NOWAIT); + if (sc->curscr == NULL) { + printf("failed to allocate screen memory!\n"); + return; + } + sc->curscr->sc = (void *)sc; + screen = sc->curscr; + + /* Setup bus space mappings. */ + if (bus_space_map(sc->iot, ODYSSEY_REG_OFFSET, ODYSSEY_REG_SIZE, + BUS_SPACE_MAP_LINEAR, &sc->ioh)) { + printf("failed to map framebuffer bus space!\n"); + return; + } + + /* Setup hardware and clear screen. */ + odyssey_setup(sc); + odyssey_fillrect(sc, 0, 0, 1280, 1024, 0x000000); + odyssey_cmd_flush(sc, 0); + + /* Set screen defaults. */ + screen->width = 1280; + screen->height = 1024; + screen->depth = 32; + screen->linebytes = screen->width * screen->depth / 8; + + odyssey_init_screen(screen); + + waa.console = sc->console; + waa.scrdata = &odyssey_screenlist; + waa.accessops = &odyssey_accessops; + waa.accesscookie = screen; + config_found(self, &waa, wsemuldisplaydevprint); +} + +void +odyssey_init_screen(struct odyssey_screen *screen) +{ + u_char *colour; + int i; + + /* + * Initialise screen. + */ + + /* Initialise rasops. */ + memset(&screen->ri, 0, sizeof(struct rasops_info)); + + screen->ri.ri_flg = RI_CENTER; + screen->ri.ri_depth = screen->depth; + screen->ri.ri_width = screen->width; + screen->ri.ri_height = screen->height; + screen->ri.ri_stride = screen->linebytes; + + if (screen->depth == 32) { + screen->ri.ri_bpos = 16; + screen->ri.ri_bnum = 8; + screen->ri.ri_gpos = 8; + screen->ri.ri_gnum = 8; + screen->ri.ri_rpos = 0; + screen->ri.ri_rnum = 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(&screen->ri, screen->height / 8, screen->width / 8); + + /* + * Initialise colourmap, if required. + */ + 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]; + } + } + + screen->ri.ri_hw = screen->sc; + + screen->ri.ri_ops.putchar = odyssey_putchar; + screen->ri.ri_do_cursor = odyssey_do_cursor; + screen->ri.ri_ops.copyrows = odyssey_copyrows; + screen->ri.ri_ops.copycols = odyssey_copycols; + screen->ri.ri_ops.eraserows = odyssey_eraserows; + screen->ri.ri_ops.erasecols = odyssey_erasecols; + + odyssey_stdscreen.ncols = screen->ri.ri_cols; + odyssey_stdscreen.nrows = screen->ri.ri_rows; + odyssey_stdscreen.textops = &screen->ri.ri_ops; + odyssey_stdscreen.fontwidth = screen->ri.ri_font->fontwidth; + odyssey_stdscreen.fontheight = screen->ri.ri_font->fontheight; + odyssey_stdscreen.capabilities = screen->ri.ri_caps; +} + +/* + * Hardware initialisation. + */ +void +odyssey_setup(struct odyssey_softc *sc) +{ + u_int64_t val; + int i; + + /* Initialise Buzz Graphics Engine. */ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x20008003); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x21008010); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x22008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x23008002); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2400800c); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2500800e); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x27008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x28008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x290080d6); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2a0080e0); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2c0080ea); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2e008380); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2f008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x30008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x31008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x32008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x33008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x34008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x35008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x310081e0); + odyssey_cmd_flush(sc, 0); + + /* Initialise Buzz X-Form. */ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x9080bda2); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0xbf800000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x4e000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x40400000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x4e000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x4d000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x34008000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x9080bdc8); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x34008010); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x908091df); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x34008000); + odyssey_cmd_flush(sc, 0); + + /* Initialise Buzz Raster. */ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0001203b); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00001000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00001000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00001000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00001000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0001084a); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000080); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000080); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010845); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000000ff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000076ff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0001141b); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000001); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011c16); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x03000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010404); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011023); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ff0ff0); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ff0ff0); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000000ff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011017); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000050); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x20004950); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0001204b); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x004ff3ff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ffffff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ffffff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ffffff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + odyssey_cmd_flush(sc, 0); + + /* + * Initalise Pixel Blaster & Jammer. + */ + for (i = 0; i < 32; i++) { + if ((i & 0xf) == 0) + odyssey_data_wait(sc); + + bus_space_write_8(sc->iot, sc->ioh, ODYSSEY_DATA_FIFO, + ((0x30000001ULL | ((0x2900 + i) << 14)) << 32) | + 0x905215a6); + } + + odyssey_data_wait(sc); + bus_space_write_8(sc->iot, sc->ioh, ODYSSEY_DATA_FIFO, + ((0x30000001ULL | (0x2581 << 14)) << 32) | 0x0); + + /* Gamma ramp. */ + for (i = 0; i < 0x600; i++) { + if ((i & 0xf) == 0) + odyssey_data_wait(sc); + + if (i < 0x200) + val = i >> 2; + else if (i < 0x300) + val = ((i - 0x200) >> 1) + 0x80; + else + val = ((i - 0x300) >> 1) + 0x100; + + val = (val << 20) | (val << 10) | val; + + bus_space_write_8(sc->iot, sc->ioh, ODYSSEY_DATA_FIFO, + ((0x30000001ULL | ((0x1a00 + i) << 14)) << 32) | val); + } +} + +void +odyssey_cmd_wait(struct odyssey_softc *sc) +{ + u_int32_t val, timeout = 1000000; + + val = bus_space_read_4(sc->iot, sc->ioh, ODYSSEY_STATUS); + while ((val & ODYSSEY_STATUS_CMD_FIFO_LOW) == 0) { + delay(1); + if (--timeout == 0) { + printf("odyssey: timeout waiting for command fifo!\n"); + return; + } + val = bus_space_read_4(sc->iot, sc->ioh, ODYSSEY_STATUS); + } +} + +void +odyssey_data_wait(struct odyssey_softc *sc) +{ + u_int32_t val, timeout = 1000000; + + val = bus_space_read_4(sc->iot, sc->ioh, ODYSSEY_DBE_STATUS); + while ((val & 0x7f) > 0) { + delay(1); + if (--timeout == 0) { + printf("odyssey: timeout waiting for data fifo!\n"); + return; + } + val = bus_space_read_4(sc->iot, sc->ioh, ODYSSEY_DBE_STATUS); + } +} + +void +odyssey_cmd_flush(struct odyssey_softc *sc, int quick) +{ + + odyssey_cmd_wait(sc); + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010443); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000000fa); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); + + if (quick) + return; + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010019); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010443); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000096); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010443); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000000fa); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); +} + +/* + * Interfaces for wscons. + */ + +int +odyssey_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct odyssey_screen *screen = (struct odyssey_screen *)v; + int rc; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_ODYSSEY; + break; + + case WSDISPLAYIO_GINFO: + { + struct wsdisplay_fbinfo *fb = (struct wsdisplay_fbinfo *)data; + + 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 = screen->linebytes; + break; + + case WSDISPLAYIO_GETCMAP: + if (screen->depth == 8) { + struct wsdisplay_cmap *cm = + (struct wsdisplay_cmap *)data; + + rc = odyssey_getcmap(&screen->cmap, cm); + if (rc != 0) + return (rc); + } + break; + + case WSDISPLAYIO_PUTCMAP: + if (screen->depth == 8) { + struct wsdisplay_cmap *cm = + (struct wsdisplay_cmap *)data; + + rc = odyssey_putcmap(&screen->cmap, cm); + if (rc != 0) + return (rc); + } + break; + + case WSDISPLAYIO_GVIDEO: + case WSDISPLAYIO_SVIDEO: + /* Handled by the upper layer. */ + break; + + default: + return (-1); + } + + return (0); +} + +int +odyssey_getcmap(struct odyssey_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 +odyssey_putcmap(struct odyssey_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); +} + +paddr_t +odyssey_mmap(void *v, off_t offset, int protection) +{ + return (-1); +} + +int +odyssey_alloc_screen(void *v, const struct wsscreen_descr *type, + void **cookiep, int *curxp, int *curyp, long *attrp) +{ + struct odyssey_screen *screen = (struct odyssey_screen *)v; + struct odyssey_softc *sc = (struct odyssey_softc *)screen->sc; + + /* We do not allow multiple consoles at the moment. */ + if (sc->screens > 0) + return (ENOMEM); + + sc->screens++; + + /* Return rasops_info via cookie. */ + *cookiep = &screen->ri; + + /* Move cursor to top left of screen. */ + *curxp = 0; + *curyp = 0; + + /* Correct screen attributes. */ + screen->ri.ri_ops.alloc_attr(&screen->ri, 0, 0, 0, attrp); + screen->attr = *attrp; + + return (0); +} + +void +odyssey_free_screen(void *v, void *cookie) +{ + /* We do not allow multiple consoles at the moment. */ +} + +int +odyssey_show_screen(void *v, void *cookie, int waitok, + void (*cb)(void *, int, int), void *cbarg) +{ + /* We do not allow multiple consoles at the moment. */ + return (0); +} + +void +odyssey_burner(void *v, u_int on, u_int flags) +{ +} + +/* + * Hardware accelerated functions. + */ + +void +odyssey_rop(struct odyssey_softc *sc, int x, int y, int w, int h, int op, int c) +{ + /* Setup raster operation. */ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010404); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00100000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_LOGIC_OP); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, op); + odyssey_cmd_flush(sc, 1); + + odyssey_fillrect(sc, x, y, w, h, c); + + /* Return to copy mode. */ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010404); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00100000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_LOGIC_OP); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, + OPENGL_LOGIC_OP_COPY); + odyssey_cmd_flush(sc, 1); +} + +void +odyssey_copyrect(struct odyssey_softc *sc, int sx, int sy, int dx, int dy, + int w, int h) +{ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010658); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00120000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002031); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, sx | (sy << 16)); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x80502050); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, w | (h << 16)); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x82223042); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, dx | (dy << 16)); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3222204b); + + odyssey_cmd_flush(sc, 1); +} + +void +odyssey_fillrect(struct odyssey_softc *sc, int x, int y, int w, int h, u_int c) +{ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_BEGIN); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_QUADS); + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_COLOR_3UB); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, c & 0xff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, (c >> 8) & 0xff); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, (c >> 16) & 0xff); + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, x); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, y); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, x + w); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, y); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, x + w); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, y + h); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, x); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, y + h); + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_END); + + odyssey_cmd_flush(sc, 1); +} + +int +odyssey_do_cursor(struct rasops_info *ri) +{ + struct odyssey_softc *sc = ri->ri_hw; + struct odyssey_screen *screen = sc->curscr; + int y, x, w, h, fg, bg; + + 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; + + ri->ri_ops.unpack_attr(ri, screen->attr, &fg, &bg, NULL); + + odyssey_rop(sc, x, y, w, h, OPENGL_LOGIC_OP_XOR, ri->ri_devcmap[fg]); + odyssey_cmd_flush(sc, 0); + + return 0; +} + +int +odyssey_putchar(void *cookie, int row, int col, u_int uc, long attr) +{ + struct rasops_info *ri = cookie; + struct odyssey_softc *sc = ri->ri_hw; + struct wsdisplay_font *font = ri->ri_font; + int x, y, w, h, bg, fg, ul, i, j, ci, l; + u_int8_t *fontbitmap; + u_int chunk; + + w = ri->ri_font->fontwidth; + h = ri->ri_font->fontheight; + x = ri->ri_xorigin + col * w; + y = ri->ri_yorigin + row * h; + + fontbitmap = (u_int8_t *)(font->data + (uc - font->firstchar) * + ri->ri_fontscale); + ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, &ul); + + /* Handle spaces with a single fillrect. */ + if (uc == ' ') { + odyssey_fillrect(sc, x, y, w, h, ri->ri_devcmap[bg]); + odyssey_cmd_flush(sc, 0); + return 0; + } + + odyssey_fillrect(sc, x, y, w, h, 0xff0000); + + /* Setup pixel painting. */ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010405); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002400); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0xc580cc08); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011453); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000002); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + odyssey_cmd_flush(sc, 0); + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2900812f); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00014400); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0000000a); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0xcf80a92f); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, ieee754_sp(x)); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, ieee754_sp(y)); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, + ieee754_sp(x + font->fontwidth)); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, + ieee754_sp(y + font->fontheight)); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x8080c800); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00004570); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0f00104c); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000071); + + for (i = font->fontheight; i != 0; i--) { + + /* Get bitmap for current line. */ + if (font->fontwidth <= 8) + chunk = *fontbitmap; + else + chunk = *(u_int16_t *)fontbitmap; + fontbitmap += font->stride; + + /* Handle underline. */ + if (ul && i == 1) + chunk = 0xffff; + + /* Draw character. */ + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, + 0x00004570); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, + 0x0fd1104c); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, + 0x00000071); + + w = font->fontwidth; + l = 0; + + for (j = 0; j < font->fontwidth; j++) { + + if (l == 0) { + + l = (w > 14 ? 14 : w); + w -= 14; + + /* Number of pixels. */ + bus_space_write_4(sc->iot, sc->ioh, + ODYSSEY_CMD_FIFO, (0x00014011 | + (l << 10))); + + } + + if (font->fontwidth > 8) + ci = (chunk & (1 << (16 - j)) ? fg : bg); + else + ci = (chunk & (1 << (8 - j)) ? fg : bg); + + bus_space_write_4(sc->iot, sc->ioh, + ODYSSEY_CMD_FIFO, ri->ri_devcmap[ci]); + + l--; + } + } + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00014001); + odyssey_cmd_flush(sc, 1); + + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x290080d6); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011453); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010405); + bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002000); + odyssey_cmd_flush(sc, 0); + + return 0; +} + +int +odyssey_copycols(void *cookie, int row, int src, int dst, int num) +{ + struct rasops_info *ri = cookie; + struct odyssey_softc *sc = ri->ri_hw; + int i; + + if (src < dst) { + + /* We cannot control copy direction, so copy col by col. */ + for (i = num - 1; i >= 0; i--) + odyssey_copyrect(sc, + ri->ri_xorigin + (src + i) * ri->ri_font->fontwidth, + ri->ri_yorigin + row * ri->ri_font->fontheight, + ri->ri_xorigin + (dst + i) * ri->ri_font->fontwidth, + ri->ri_yorigin + row * ri->ri_font->fontheight, + ri->ri_font->fontwidth, ri->ri_font->fontheight); + + } else { + + odyssey_copyrect(sc, + ri->ri_xorigin + src * ri->ri_font->fontwidth, + ri->ri_yorigin + row * ri->ri_font->fontheight, + ri->ri_xorigin + dst * ri->ri_font->fontwidth, + ri->ri_yorigin + row * ri->ri_font->fontheight, + num * ri->ri_font->fontwidth, ri->ri_font->fontheight); + + } + + odyssey_cmd_flush(sc, 0); + + return 0; +} + +int +odyssey_erasecols(void *cookie, int row, int col, int num, long attr) +{ + struct rasops_info *ri = cookie; + struct odyssey_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; + + odyssey_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, + num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); + odyssey_cmd_flush(sc, 0); + + return 0; +} + +int +odyssey_copyrows(void *cookie, int src, int dst, int num) +{ + struct rasops_info *ri = cookie; + struct odyssey_softc *sc = ri->ri_hw; + int i; + + if (src < dst) { + + /* We cannot control copy direction, so copy row by row. */ + for (i = num - 1; i >= 0; i--) + odyssey_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + + (src + i) * ri->ri_font->fontheight, + ri->ri_xorigin, ri->ri_yorigin + + (dst + i) * ri->ri_font->fontheight, + ri->ri_emuwidth, ri->ri_font->fontheight); + + } else { + + odyssey_copyrect(sc, ri->ri_xorigin, + ri->ri_yorigin + src * ri->ri_font->fontheight, + ri->ri_xorigin, + ri->ri_yorigin + dst * ri->ri_font->fontheight, + ri->ri_emuwidth, num * ri->ri_font->fontheight); + + } + + odyssey_cmd_flush(sc, 0); + + return 0; +} + +int +odyssey_eraserows(void *cookie, int row, int num, long attr) +{ + struct rasops_info *ri = cookie; + struct odyssey_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; + } + + odyssey_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); + odyssey_cmd_flush(sc, 0); + + return 0; +} + +u_int32_t +ieee754_sp(int32_t v) +{ + u_int8_t exp = 0, sign = 0; + int i = 32; + + /* + * Convert an integer to IEEE754 single precision floating point: + * + * Sign - 1 bit + * Exponent - 8 bits (with 2^(8-1)-1 = 127 bias) + * Fraction - 23 bits + */ + + if (v < 0) { + sign = 1; + v = -v; + } + + /* Determine shift for fraction. */ + while (i && (v & (1 << --i)) == 0); + + if (v != 0) + exp = 127 + i; + + return (sign << 31) | (exp << 23) | ((v << (23 - i)) & 0x7fffff); +} diff --git a/sys/arch/sgi/xbow/odysseyreg.h b/sys/arch/sgi/xbow/odysseyreg.h new file mode 100644 index 00000000000..5464cb2efaf --- /dev/null +++ b/sys/arch/sgi/xbow/odysseyreg.h @@ -0,0 +1,62 @@ +/* $OpenBSD: odysseyreg.h,v 1.1 2010/03/04 14:50:35 jsing Exp $ */ +/* + * Copyright (c) 2009, 2010 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Register details for the SGI VPro (aka Odyssey) Graphics Card. + */ + +#define ODYSSEY_REG_OFFSET 0x00000000 +#define ODYSSEY_REG_SIZE 0x00410000 + +#define ODYSSEY_STATUS 0x00001064 +#define ODYSSEY_STATUS_CMD_FIFO_HIGH 0x00008000 +#define ODYSSEY_STATUS_CMD_FIFO_LOW 0x00020000 +#define ODYSSEY_DBE_STATUS 0x0000106c + +#define ODYSSEY_CMD_FIFO 0x00110000 +#define ODYSSEY_DATA_FIFO 0x00400000 + +/* + * OpenGL Commands. + */ + +#define OPENGL_BEGIN 0x00014400 +#define OPENGL_END 0x00014001 +#define OPENGL_LOGIC_OP 0x00010422 +#define OPENGL_VERTEX_2I 0x8080c800 +#define OPENGL_COLOR_3UB 0xc580cc08 + +#define OPENGL_QUADS 0x00000007 + +/* Logic Operations. */ +#define OPENGL_LOGIC_OP_CLEAR 0 +#define OPENGL_LOGIC_OP_AND 1 +#define OPENGL_LOGIC_OP_AND_REVERSE 2 +#define OPENGL_LOGIC_OP_COPY 3 +#define OPENGL_LOGIC_OP_AND_INVERTED 4 +#define OPENGL_LOGIC_OP_NOOP 5 +#define OPENGL_LOGIC_OP_XOR 6 +#define OPENGL_LOGIC_OP_OR 7 +#define OPENGL_LOGIC_OP_NOR 8 +#define OPENGL_LOGIC_OP_EQUIV 9 +#define OPENGL_LOGIC_OP_INVERT 10 +#define OPENGL_LOGIC_OP_OR_REVERSE 11 +#define OPENGL_LOGIC_OP_COPY_INVERTED 12 +#define OPENGL_LOGIC_OP_OR_INVERTED 13 +#define OPENGL_LOGIC_OP_NAND 14 +#define OPENGL_LOGIC_OP_SET 15 + |