diff options
Diffstat (limited to 'sys/dev/fb/gfb.c')
-rw-r--r-- | sys/dev/fb/gfb.c | 941 |
1 files changed, 941 insertions, 0 deletions
diff --git a/sys/dev/fb/gfb.c b/sys/dev/fb/gfb.c new file mode 100644 index 0000000..4e03169 --- /dev/null +++ b/sys/dev/fb/gfb.c @@ -0,0 +1,941 @@ +/*- + * Copyright (c) 2001 Andrew Miklic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <machine/stdarg.h> + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/fbio.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + +#include <machine/md_var.h> +#include <machine/pc/bios.h> +#include <machine/clock.h> +#include <machine/bus_memio.h> +#include <machine/bus.h> +#include <machine/pc/vesa.h> +#include <machine/resource.h> +#include <machine/rpb.h> + +#include <sys/bus.h> +#include <sys/rman.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <dev/fb/fbreg.h> +#include <dev/fb/gfb.h> +#include <dev/gfb/gfb_pci.h> + +#include "opt_gfb.h" + +struct gfb_softc *gfb_device_softcs[2][MAX_NUM_GFB_CARDS] = { + { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, + { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, +}; + +/* + The following 9 variables exist only because we need statically + allocated structures very early in boot to support gfb_configure()... +*/ +struct gfb_softc console; +video_adapter_t console_adp; +struct gfb_conf console_gfbc; +u_char console_palette_red[256]; +u_char console_palette_green[256]; +u_char console_palette_blue[256]; +u_char console_cursor_palette_red[3]; +u_char console_cursor_palette_green[3]; +u_char console_cursor_palette_blue[3]; + +extern struct gfb_font bold8x16; + +/***************************************************************************** + * + * FB-generic functions + * + ****************************************************************************/ + +int +gfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags) +{ + int error; + + /* Assume the best... */ + error = 0; + + if((*adpp = vid_get_adapter(vid_find_adapter((char *)arg, unit))) == NULL) + error = ENODEV; + else + (*adpp)->va_flags |= V_ADP_PROBED; + + return(error); +} + +int +gfb_init(int unit, video_adapter_t *adp, int flags) +{ + struct gfb_softc *sc; + struct gfb_conf *gfbc; + int error; + + /* Assume the best... */ + error = 0; + + if(!init_done(adp)) { + sc = gfb_device_softcs[adp->va_model][unit]; + gfbc = sc->gfbc; + + /* Initialize the RAMDAC... */ + (*gfbc->ramdac_init)(sc); + + /* Initialize the palettes... */ + (*gfbc->ramdac_load_palette)(sc->adp, &sc->gfbc->palette); + (*gfbc->ramdac_load_cursor_palette)(sc->adp, + &sc->gfbc->cursor_palette); + + /* Prepare the default font... */ + (*vidsw[adp->va_index]->load_font)(adp, 0, bold8x16.height, + bold8x16.data, 0, 256); + adp->va_info.vi_cwidth = gfbc->fonts[0].width; + adp->va_info.vi_cheight = gfbc->fonts[0].height; + + /* + Normalize vi_width and vi_height to be in terms of + on-screen characters, rather than pixels (*_init() + leaves them in terms of pixels... + */ + adp->va_info.vi_width /= adp->va_info.vi_cwidth; + adp->va_info.vi_height /= adp->va_info.vi_cheight; + + /* Enable the default font... */ + (*vidsw[adp->va_index]->show_font)(adp, 0); + + /* Enable future font-loading... */ + adp->va_flags |= V_ADP_FONT; + + /* Flag this initialization for this adapter... */ + adp->va_flags |= V_ADP_INITIALIZED; + } + return(error); +} + +int +gfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) +{ + int error; + + /* Assume the best... */ + error = 0; + + /* + The info for GFB adapters does not depend on its mode, + so just copy it indiscriminantly (actually, we originally + checked the mode, but the current fb framework is somewhat + sloppily done in places, and assumes VGA in several places, + which makes such checks always fail for such GFBs as TGA)... + */ + bcopy(&adp->va_info, info, sizeof(video_info_t)); + return(error); +} + +int +gfb_set_mode(video_adapter_t *adp, int mode) +{ + + adp->va_mode = mode; + return(0); +} + +int +gfb_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, + int ch, int count) +{ + struct gfb_softc *sc; + int error; + int i; + + error = 0; + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + /* Check the font information... */ + if((sc->gfbc->fonts[page].height != fontsize) || + (sc->gfbc->fonts[page].width != 8)) + error = EINVAL; + else + + /* + Copy the character pixel array from our + very own private cache... + */ + for(i = ch; i < count * fontsize; i++) + data[i] = adp->va_little_bitian ? + BIT_REVERSE(sc->gfbc->fonts[page].data[i]) : + sc->gfbc->fonts[page].data[i]; + + return(error); +} + +int +gfb_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, + int ch, int count) +{ + struct gfb_softc *sc; + int error; + int i; + + error = 0; + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + /* Copy the character pixel array into our very own private cache... */ + for(i = ch; i < count * fontsize; i++) + sc->gfbc->fonts[page].data[i] = adp->va_little_bitian ? + BIT_REVERSE(data[i]) : data[i]; + + /* Save the font information... */ + sc->gfbc->fonts[page].height = fontsize; + sc->gfbc->fonts[page].width = 8; + + return(error); +} + +int +gfb_show_font(video_adapter_t *adp, int page) +{ + struct gfb_softc *sc; + int error; + + error = 0; + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + /* Normalize adapter values... */ + adp->va_info.vi_height *= adp->va_info.vi_cheight; + adp->va_info.vi_width *= adp->va_info.vi_cwidth; + + /* Set the current font pixels... */ + sc->gfbc->font = sc->gfbc->fonts[page].data; + + /* Set the current font width... */ + adp->va_info.vi_cwidth = sc->gfbc->fonts[page].width; + + /* Set the current font height... */ + adp->va_info.vi_cheight = sc->gfbc->fonts[page].height; + + /* Recompute adapter values... */ + adp->va_info.vi_height /= adp->va_info.vi_cheight; + adp->va_info.vi_width /= adp->va_info.vi_cwidth; + + return(error); +} + +int +gfb_save_palette(video_adapter_t *adp, u_char *palette) +{ + struct gfb_softc *sc; + int error; + int i; + + error = 0; + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + +#if 0 + /* If we have a RAMDAC-specific counterpart, use it... */ + if(sc->gfbc->ramdac_save_palette) + error = sc->gfbc->ramdac_save_palette(adp, &sc->gfbc->palette); + + else + /* Otherwise, use the built-in functionality... */ + error = sc->gfbc->builtin_save_palette(adp, &sc->gfbc->palette); +#endif + + for(i = 0; i < sc->gfbc->palette.count; i++) { + palette[(3 * i)] = sc->gfbc->palette.red[i]; + palette[(3 * i) + 1] = sc->gfbc->palette.green[i]; + palette[(3 * i) + 2] = sc->gfbc->palette.blue[i]; + } + return(error); +} + +int +gfb_load_palette(video_adapter_t *adp, u_char *palette) +{ + struct gfb_softc *sc; + int error; + int i; + + error = 0; + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + for(i = 0; i < sc->gfbc->palette.count; i++) { + sc->gfbc->palette.red[i] = palette[(3 * i)]; + sc->gfbc->palette.green[i] = palette[(3 * i) + 1]; + sc->gfbc->palette.blue[i] = palette[(3 * i) + 2]; + } + + /* If we have a RAMDAC-specific counterpart, use it... */ + if(sc->gfbc->ramdac_load_palette) + error = sc->gfbc->ramdac_load_palette(adp, &sc->gfbc->palette); + else + /* Otherwise, use the built-in functionality... */ + error = sc->gfbc->builtin_load_palette(adp, &sc->gfbc->palette); + + return(error); +} + +int +gfb_set_border(video_adapter_t *adp, int color) +{ + + return(ENODEV); +} + +int +gfb_save_state(video_adapter_t *adp, void *p, size_t size) +{ + int i; + u_int32_t *regs; + + regs = (u_int32_t *)p; + regs[0] = size; + for(i = 1; i <= size; i++) + regs[i] = READ_GFB_REGISTER(adp, i); + return(0); +} + +int +gfb_load_state(video_adapter_t *adp, void *p) +{ + size_t size; + int i; + u_int32_t *regs; + + regs = (u_int32_t *)p; + size = regs[0]; + for(i = 1; i <= size; i++) + WRITE_GFB_REGISTER(adp, i, regs[i]); + return(0); +} + +int +gfb_set_win_org(video_adapter_t *adp, off_t offset) +{ + + adp->va_window_orig = offset; + return(0); +} + +int +gfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) +{ + struct gfb_softc *sc; + int error; + + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + /* If we have a RAMDAC-specific counterpart, use it... */ + if(sc->gfbc->ramdac_read_hw_cursor) + error = sc->gfbc->ramdac_read_hw_cursor(adp, col, row); + else + /* Otherwise, use the built-in functionality... */ + error = sc->gfbc->builtin_read_hw_cursor(adp, col, row); + + return(error); +} + +int +gfb_set_hw_cursor(adp, col, row) + video_adapter_t *adp; + int col; + int row; +{ + int error; + struct gfb_softc *sc; + + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + /* If we have a RAMDAC-specific counterpart, use it... */ + if(sc->gfbc->ramdac_set_hw_cursor) + error = sc->gfbc->ramdac_set_hw_cursor(adp, col, row); + + /* Otherwise, use the built-in functionality... */ + else + error = sc->gfbc->builtin_set_hw_cursor(adp, col, row); + return(error); +} + +int +gfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, + int cellsize, int blink) +{ + struct gfb_softc *sc; + int error; + + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + /* If we have a RAMDAC-specific counterpart, use it... */ + if(sc->gfbc->ramdac_set_hw_cursor_shape) + error = sc->gfbc->ramdac_set_hw_cursor_shape(adp, base, height, + cellsize, blink); + else + /* Otherwise, use the built-in functionality... */ + error = sc->gfbc->builtin_set_hw_cursor_shape(adp, base, + height, cellsize, blink); + + return(error); +} + +int +gfb_mmap(video_adapter_t *adp, vm_offset_t offset, vm_offset_t *paddr, int prot) +{ + + /* XXX */ + if(offset > adp->va_window_size - PAGE_SIZE) + return(ENXIO); + *paddr = adp->va_info.vi_window + offset; + return(0); +} + +int +gfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) +{ + struct gfb_softc *sc; + int error; + + error = 0; + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + switch (cmd) { + case FBIOPUTCMAP: + /* FALLTHROUGH */ + case FBIO_GETWINORG: + /* FALLTHROUGH */ + case FBIO_SETWINORG: + /* FALLTHROUGH */ + case FBIO_SETDISPSTART: + /* FALLTHROUGH */ + case FBIO_SETLINEWIDTH: + /* FALLTHROUGH */ + case FBIO_GETPALETTE: + /* FALLTHROUGH */ + case FBIOGTYPE: + /* FALLTHROUGH */ + case FBIOGETCMAP: + /* FALLTHROUGH */ + default: + error = fb_commonioctl(adp, cmd, arg); + } + return(error); +} + +int +gfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) +{ + int off; + + /* + Just traverse the buffer, one pixel span at a time, setting + each pixel to the block-color... + */ + for(off = (x * y); off < ((x + cx) * (y + cy)); off++) + (*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff, + sizeof(u_int32_t), 1, 0, 0); + + return(0); +} + +int +gfb_bitblt(video_adapter_t *adp, ...) +{ + va_list args; + vm_offset_t src, dst; + int count, i; + u_int32_t val; + + va_start(args, adp); + + src = (va_arg(args, vm_offset_t) + adp->va_window_orig) & + 0x0000000000fffff8; + dst = (va_arg(args, vm_offset_t) + adp->va_window_orig) & + 0x0000000000fffff8; + count = va_arg(args, int); + for(i = 0; i < count; i++, src++, dst++) { + val = READ_GFB_BUFFER(adp, src); + WRITE_GFB_BUFFER(adp, dst, val); + } + va_end(args); + return(0); +} + +int +/*gfb_clear(video_adapter_t *adp, int n)*/ +gfb_clear(video_adapter_t *adp) +{ + int off; + +#if 0 + if(n == 0) + return(0); +#endif + + /* + Just traverse the buffer, one 2K-pixel span at a time, clearing + each pixel... + */ + /* for(off = 0; off < (n * adp->va_line_width); off += (2 KB)) */ + for(off = 0; off < adp->va_window_size; off++) + (*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff, + sizeof(u_int32_t), 1, 0, 0); + + return(0); +} + +int +gfb_diag(video_adapter_t *adp, int level) +{ + video_info_t info; + struct gfb_softc *sc; + int error; + + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + /* Just dump everything we know about the adapter to the screen... */ + fb_dump_adp_info(sc->driver_name, adp, level); + + /* Try to get the info on this adapter... */ + if(!(error = (*vidsw[adp->va_index]->get_info)(adp, + adp->va_initial_mode, &info))) + /* + Just dump everything we know about the adapter's mode + to the screen... + */ + fb_dump_mode_info(sc->driver_name, adp, &info, level); + + return(error); +} + +int +gfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) +{ + struct gfb_softc *sc; + int error, i; + + error = 0; + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + +#if 0 + /* If we have a RAMDAC-specific counterpart, use it... */ + if(sc->gfbc->ramdac_save_cursor_palette) + error = sc->gfbc->ramdac_save_cursor_palette(adp, + &sc->gfbc->cursor_palette); + + else + /* Otherwise, use the built-in functionality... */ + error = sc->gfbc->builtin_save_cursor_palette(adp, + &sc->gfbc->cursor_palette); +#endif + + for(i = 0; i < sc->gfbc->cursor_palette.count; i++) { + palette[(3 * i)] = sc->gfbc->cursor_palette.red[i]; + palette[(3 * i) + 1] = sc->gfbc->cursor_palette.green[i]; + palette[(3 * i) + 2] = sc->gfbc->cursor_palette.blue[i]; + } + return(error); +} + +int +gfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) +{ + struct gfb_softc *sc; + int error, i; + + error = 0; + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + for(i = 0; i < sc->gfbc->cursor_palette.count; i++) { + sc->gfbc->cursor_palette.red[i] = palette[(3 * i)]; + sc->gfbc->cursor_palette.green[i] = palette[(3 * i) + 1]; + sc->gfbc->cursor_palette.blue[i] = palette[(3 * i) + 2]; + } + + /* If we have a RAMDAC-specific counterpart, use it... */ + if(sc->gfbc->ramdac_load_cursor_palette) + error = sc->gfbc->ramdac_load_cursor_palette(adp, + &sc->gfbc->cursor_palette); + else + /* Otherwise, use the built-in functionality... */ + error = sc->gfbc->builtin_load_cursor_palette(adp, + &sc->gfbc->cursor_palette); + + return(error); +} + +int +gfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) +{ + int error, num_pixels; + + if(n == 0) + return(0); + num_pixels = adp->va_info.vi_cheight * adp->va_line_width; + error = (*vidsw[adp->va_index]->bitblt)(adp, src * num_pixels, + dst * num_pixels, n * num_pixels); + return(error); +} + +int +gfb_putp(video_adapter_t *adp, vm_offset_t off, u_int32_t p, u_int32_t a, + int size, int bpp, int bit_ltor, int byte_ltor) +{ + int i, j, k, num_shifts; + u_int32_t _p, val[32]; + + if(bpp < 1) + return(-1); + + /* + If we don't display bits right-to-left (little-bitian?), + then perform a bit-swap on p... + */ + if(bit_ltor) { + num_shifts = 8 * size; + for(i = 0, _p = 0; i < num_shifts; i++, p >>= 1) { + _p <<= 1; + _p |= (p & 0x00000001); + } + } else + _p = p; + + switch(bpp) { + /* Accelerate the simplest cases... */ + case 1: + if((a & 0x00000001) == 0) + val[0] = 0; + else if(size <= 0) + val[0] = 0; + else if(size == 1) + val[0] = _p & 0x000000ff; + else if(size == 2) + val[0] = _p & 0x0000ffff; + else if(size == 3) + val[0] = _p & 0x00ffffff; + else if(size == 4) + val[0] = _p & 0xffffffff; + break; + + /* Only do the following if we are not a simple case... */ + case 8: + if(size > 0) { + a &= 0x000000ff; + val[0] = 0; + if(_p & 0x00000001) val[0] |= (a); + if(_p & 0x00000002) val[0] |= (a << 8); + if(_p & 0x00000004) val[0] |= (a << 16); + if(_p & 0x00000008) val[0] |= (a << 24); + val[1] = 0; + if(_p & 0x00000010) val[1] |= (a); + if(_p & 0x00000020) val[1] |= (a << 8); + if(_p & 0x00000040) val[1] |= (a << 16); + if(_p & 0x00000080) val[1] |= (a << 24); + } + if(size > 1) { + val[2] = 0; + if(_p & 0x00000100) val[2] |= (a); + if(_p & 0x00000200) val[2] |= (a << 8); + if(_p & 0x00000400) val[2] |= (a << 16); + if(_p & 0x00000800) val[2] |= (a << 24); + val[3] = 0; + if(_p & 0x00001000) val[3] |= (a); + if(_p & 0x00002000) val[3] |= (a << 8); + if(_p & 0x00004000) val[3] |= (a << 16); + if(_p & 0x00008000) val[3] |= (a << 24); + } + if(size > 2) { + val[4] = 0; + if(_p & 0x00010000) val[4] |= (a); + if(_p & 0x00020000) val[4] |= (a << 8); + if(_p & 0x00040000) val[4] |= (a << 16); + if(_p & 0x00080000) val[4] |= (a << 24); + val[5] = 0; + if(_p & 0x00100000) val[5] |= (a); + if(_p & 0x00200000) val[5] |= (a << 8); + if(_p & 0x00400000) val[5] |= (a << 16); + if(_p & 0x00800080) val[5] |= (a << 24); + } + if(size > 3) { + val[6] = 0; + if(_p & 0x01000000) val[6] |= (a); + if(_p & 0x02000000) val[6] |= (a << 8); + if(_p & 0x04000000) val[6] |= (a << 16); + if(_p & 0x08000000) val[6] |= (a << 24); + val[7] = 0; + if(_p & 0x10000000) val[7] |= (a); + if(_p & 0x20000000) val[7] |= (a << 8); + if(_p & 0x40000000) val[7] |= (a << 16); + if(_p & 0x80000000) val[7] |= (a << 24); + } + break; + case 16: + if(size > 0) { + a &= 0x0000ffff; + if(_p & 0x00000001) val[0] |= (a); + if(_p & 0x00000002) val[0] |= (a << 16); + if(_p & 0x00000004) val[1] |= (a); + if(_p & 0x00000008) val[1] |= (a << 16); + if(_p & 0x00000010) val[2] |= (a); + if(_p & 0x00000020) val[2] |= (a << 16); + if(_p & 0x00000040) val[3] |= (a); + if(_p & 0x00000080) val[3] |= (a << 16); + } + if(size > 1) { + if(_p & 0x00000100) val[4] |= (a); + if(_p & 0x00000200) val[4] |= (a << 16); + if(_p & 0x00000400) val[5] |= (a); + if(_p & 0x00000800) val[5] |= (a << 16); + if(_p & 0x00001000) val[6] |= (a); + if(_p & 0x00002000) val[6] |= (a << 16); + if(_p & 0x00004000) val[7] |= (a); + if(_p & 0x00008000) val[7] |= (a << 16); + } + if(size > 2) { + if(_p & 0x00010000) val[8] |= (a); + if(_p & 0x00020000) val[8] |= (a << 16); + if(_p & 0x00040000) val[9] |= (a); + if(_p & 0x00080000) val[9] |= (a << 16); + if(_p & 0x00100000) val[10] |= (a); + if(_p & 0x00200000) val[10] |= (a << 16); + if(_p & 0x00400000) val[11] |= (a); + if(_p & 0x00800000) val[11] |= (a << 16); + } + if(size > 3) { + if(_p & 0x01000000) val[12] |= (a); + if(_p & 0x02000000) val[12] |= (a << 16); + if(_p & 0x04000000) val[13] |= (a); + if(_p & 0x08000000) val[13] |= (a << 16); + if(_p & 0x10000000) val[14] |= (a); + if(_p & 0x20000000) val[14] |= (a << 16); + if(_p & 0x40000000) val[15] |= (a); + if(_p & 0x80000000) val[15] |= (a << 16); + } + break; + case 32: + if(size > 0) { + a &= 0xffffffff; + if(_p & 0x00000001) val[0] = (a); + if(_p & 0x00000002) val[1] = (a); + if(_p & 0x00000004) val[2] = (a); + if(_p & 0x00000008) val[3] = (a); + if(_p & 0x00000010) val[4] = (a); + if(_p & 0x00000020) val[5] = (a); + if(_p & 0x00000040) val[6] = (a); + if(_p & 0x00000080) val[7] = (a); + } + if(size > 1) { + if(_p & 0x00000100) val[8] = (a); + if(_p & 0x00000200) val[9] = (a); + if(_p & 0x00000400) val[10] = (a); + if(_p & 0x00000800) val[11] = (a); + if(_p & 0x00001000) val[12] = (a); + if(_p & 0x00002000) val[13] = (a); + if(_p & 0x00004000) val[14] = (a); + if(_p & 0x00008000) val[15] = (a); + } + if(size > 2) { + if(_p & 0x00010000) val[16] = (a); + if(_p & 0x00020000) val[17] = (a); + if(_p & 0x00040000) val[18] = (a); + if(_p & 0x00080000) val[19] = (a); + if(_p & 0x00100000) val[20] = (a); + if(_p & 0x00200000) val[21] = (a); + if(_p & 0x00400000) val[22] = (a); + if(_p & 0x00800000) val[23] = (a); + } + if(size > 3) { + if(_p & 0x01000000) val[24] = (a); + if(_p & 0x02000000) val[25] = (a); + if(_p & 0x04000000) val[26] = (a); + if(_p & 0x08000000) val[27] = (a); + if(_p & 0x10000000) val[28] = (a); + if(_p & 0x20000000) val[29] = (a); + if(_p & 0x40000000) val[30] = (a); + if(_p & 0x80000000) val[31] = (a); + } + break; + default: + break; + } + j = (bpp == 1) ? 1 : bpp * size / sizeof(u_int32_t); + + /* + If we don't display bytes right-to-left (little-endian), + then perform a byte-swap on p (we don't have to swap if + bpp == 1 and val[0] == 0)... + */ + if((byte_ltor) && (j > 1) && (val[j] != 0)) { + for(i = 0; i < (j - i); i++) { + _p = val[j - i]; + val[j - i] = val[i]; + val[i] = _p; + } + for(i = 0; i < j; i++) { + _p = val[i]; + for(k = 0, val[i] = 0; k < sizeof(u_int32_t); + k++, _p >>= 8) { + val[i] <<= 8; + val[i] |= (_p & 0xff); + } + } + } + + for(i = 0; i < j; i++) { + /* Write the pixel-row... */ + WRITE_GFB_BUFFER(adp, (off + i), val[i]); + } + return(0); +} + +int +gfb_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a) +{ + vm_offset_t poff; + struct gfb_softc *sc; + int i, pixel_size; + u_int row, col; + u_int8_t *pixel; + + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + pixel_size = adp->va_info.vi_depth / 8; + + /* Get the start of the array of pixels rows for this character... */ + pixel = sc->gfbc->font + (c * adp->va_info.vi_cheight); + + /* Calculate the new cursor position... */ + row = off / adp->va_info.vi_width; + col = off % adp->va_info.vi_width; + + /* Iterate over all the pixel rows for this character... */ + for(i = 0; i < adp->va_info.vi_cheight; i++) { + /* Get the address of the character's pixel-row... */ + poff = ((col * adp->va_info.vi_cwidth * pixel_size) + + (((row * adp->va_info.vi_cheight) + i) * + adp->va_line_width)) / sizeof(u_int32_t); + + /* Now display the current pixel row... */ + (*vidsw[adp->va_index]->putp)(adp, poff, pixel[i], a, + sizeof(u_int8_t), 1, 1, 0); + } + return(0); +} + +int +gfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) +{ + struct gfb_softc *sc; + int i; + + sc = gfb_device_softcs[adp->va_model][adp->va_unit]; + + /* If the string in empty, just return now... */ + if(len == 0) + return(0); + + for(i = 0; i < len; i++) + (*vidsw[adp->va_index]->putc)(adp, off + i, s[i] & 0x00ff, + (s[i] & 0xff00) >> 8); + + return(0); +} + +int +gfb_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image, + u_int32_t pixel_mask, int size) +{ + vm_offset_t poff; + int i, pixel_size; + + pixel_size = adp->va_info.vi_depth / 8; + + /* Iterate over all the pixel rows for the mouse pointer... */ + for(i = 0; i < size; i++) { + /* Get the address of the mouse pointer's pixel-row... */ + poff = ((x * pixel_size) + ((y + i) * adp->va_line_width)) / + sizeof(u_int32_t); + /* Now display the current pixel-row... */ + (*vidsw[adp->va_index]->putp)(adp, poff, pixel_image[i], + pixel_mask, sizeof(u_int8_t), 1, 1, 0); + } + + return(0); +} + +int +gfb_error(void) +{ + + return(0); +} |