scvgarndr.c revision 205605
160484Sobrien/*- 260484Sobrien * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 360484Sobrien * All rights reserved. 460484Sobrien * 560484Sobrien * This code is derived from software contributed to The DragonFly Project 660484Sobrien * by Sascha Wildner <saw@online.de> 760484Sobrien * 860484Sobrien * Redistribution and use in source and binary forms, with or without 960484Sobrien * modification, are permitted provided that the following conditions 1060484Sobrien * are met: 1160484Sobrien * 1. Redistributions of source code must retain the above copyright 1260484Sobrien * notice, this list of conditions and the following disclaimer as 1360484Sobrien * the first lines of this file unmodified. 1460484Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1560484Sobrien * notice, this list of conditions and the following disclaimer in the 1660484Sobrien * documentation and/or other materials provided with the distribution. 1760484Sobrien * 1860484Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1960484Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2060484Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2160484Sobrien * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2260484Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2360484Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2460484Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2560484Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2660484Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2760484Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2860484Sobrien * 2960484Sobrien */ 3060484Sobrien 3160484Sobrien#include <sys/cdefs.h> 3260484Sobrien__FBSDID("$FreeBSD: head/sys/dev/syscons/scvgarndr.c 205605 2010-03-24 15:40:18Z jkim $"); 3360484Sobrien 3460484Sobrien#include "opt_syscons.h" 3560484Sobrien#include "opt_vga.h" 3660484Sobrien 3760484Sobrien#include <sys/param.h> 3860484Sobrien#include <sys/systm.h> 3960484Sobrien#include <sys/kernel.h> 4060484Sobrien#include <sys/module.h> 4160484Sobrien#include <sys/fbio.h> 4260484Sobrien#include <sys/consio.h> 4360484Sobrien 4460484Sobrien#include <machine/bus.h> 4560484Sobrien 4660484Sobrien#include <dev/fb/fbreg.h> 4760484Sobrien#include <dev/fb/vgareg.h> 4860484Sobrien#include <dev/syscons/syscons.h> 4960484Sobrien 5060484Sobrien#include <isa/isareg.h> 5160484Sobrien 5260484Sobrien#ifndef SC_RENDER_DEBUG 5360484Sobrien#define SC_RENDER_DEBUG 0 5460484Sobrien#endif 5560484Sobrien 5660484Sobrienstatic vr_clear_t vga_txtclear; 5760484Sobrienstatic vr_draw_border_t vga_txtborder; 5860484Sobrienstatic vr_draw_t vga_txtdraw; 5960484Sobrienstatic vr_set_cursor_t vga_txtcursor_shape; 6060484Sobrienstatic vr_draw_cursor_t vga_txtcursor; 6160484Sobrienstatic vr_blink_cursor_t vga_txtblink; 6260484Sobrien#ifndef SC_NO_CUTPASTE 6360484Sobrienstatic vr_draw_mouse_t vga_txtmouse; 6460484Sobrien#else 6560484Sobrien#define vga_txtmouse (vr_draw_mouse_t *)vga_nop 6660484Sobrien#endif 6760484Sobrien 6860484Sobrien#ifdef SC_PIXEL_MODE 6960484Sobrienstatic vr_init_t vga_rndrinit; 7060484Sobrienstatic vr_clear_t vga_pxlclear_direct; 7160484Sobrienstatic vr_clear_t vga_pxlclear_planar; 7260484Sobrienstatic vr_draw_border_t vga_pxlborder_direct; 7360484Sobrienstatic vr_draw_border_t vga_pxlborder_planar; 7460484Sobrienstatic vr_draw_t vga_egadraw; 7560484Sobrienstatic vr_draw_t vga_vgadraw_direct; 7660484Sobrienstatic vr_draw_t vga_vgadraw_planar; 7760484Sobrienstatic vr_set_cursor_t vga_pxlcursor_shape; 7860484Sobrienstatic vr_draw_cursor_t vga_pxlcursor_direct; 7960484Sobrienstatic vr_draw_cursor_t vga_pxlcursor_planar; 8060484Sobrienstatic vr_blink_cursor_t vga_pxlblink_direct; 8160484Sobrienstatic vr_blink_cursor_t vga_pxlblink_planar; 8260484Sobrien#ifndef SC_NO_CUTPASTE 8360484Sobrienstatic vr_draw_mouse_t vga_pxlmouse_direct; 8460484Sobrienstatic vr_draw_mouse_t vga_pxlmouse_planar; 8560484Sobrien#else 8660484Sobrien#define vga_pxlmouse_direct (vr_draw_mouse_t *)vga_nop 8760484Sobrien#define vga_pxlmouse_planar (vr_draw_mouse_t *)vga_nop 8860484Sobrien#endif 8960484Sobrien#endif /* SC_PIXEL_MODE */ 9060484Sobrien 9160484Sobrien#ifndef SC_NO_MODE_CHANGE 9260484Sobrienstatic vr_draw_border_t vga_grborder; 9360484Sobrien#endif 9460484Sobrien 9560484Sobrienstatic void vga_nop(scr_stat *scp); 9660484Sobrien 9760484Sobrienstatic sc_rndr_sw_t txtrndrsw = { 9860484Sobrien (vr_init_t *)vga_nop, 9960484Sobrien vga_txtclear, 10060484Sobrien vga_txtborder, 10160484Sobrien vga_txtdraw, 10260484Sobrien vga_txtcursor_shape, 10360484Sobrien vga_txtcursor, 10460484Sobrien vga_txtblink, 10560484Sobrien (vr_set_mouse_t *)vga_nop, 10660484Sobrien vga_txtmouse, 10760484Sobrien}; 10860484SobrienRENDERER(mda, 0, txtrndrsw, vga_set); 10960484SobrienRENDERER(cga, 0, txtrndrsw, vga_set); 11060484SobrienRENDERER(ega, 0, txtrndrsw, vga_set); 11160484SobrienRENDERER(vga, 0, txtrndrsw, vga_set); 11260484Sobrien 11360484Sobrien#ifdef SC_PIXEL_MODE 11460484Sobrienstatic sc_rndr_sw_t egarndrsw = { 11560484Sobrien (vr_init_t *)vga_nop, 11660484Sobrien vga_pxlclear_planar, 11760484Sobrien vga_pxlborder_planar, 11860484Sobrien vga_egadraw, 11960484Sobrien vga_pxlcursor_shape, 12060484Sobrien vga_pxlcursor_planar, 12160484Sobrien vga_pxlblink_planar, 12260484Sobrien (vr_set_mouse_t *)vga_nop, 12360484Sobrien vga_pxlmouse_planar, 12460484Sobrien}; 12560484SobrienRENDERER(ega, PIXEL_MODE, egarndrsw, vga_set); 12677298Sobrien 12777298Sobrienstatic sc_rndr_sw_t vgarndrsw = { 12877298Sobrien vga_rndrinit, 12977298Sobrien (vr_clear_t *)vga_nop, 13077298Sobrien (vr_draw_border_t *)vga_nop, 13177298Sobrien (vr_draw_t *)vga_nop, 13277298Sobrien vga_pxlcursor_shape, 13377298Sobrien (vr_draw_cursor_t *)vga_nop, 13477298Sobrien (vr_blink_cursor_t *)vga_nop, 13577298Sobrien (vr_set_mouse_t *)vga_nop, 13677298Sobrien (vr_draw_mouse_t *)vga_nop, 13777298Sobrien}; 13877298SobrienRENDERER(vga, PIXEL_MODE, vgarndrsw, vga_set); 13977298Sobrien#endif /* SC_PIXEL_MODE */ 14077298Sobrien 14177298Sobrien#ifndef SC_NO_MODE_CHANGE 14277298Sobrienstatic sc_rndr_sw_t grrndrsw = { 14360484Sobrien (vr_init_t *)vga_nop, 14477298Sobrien (vr_clear_t *)vga_nop, 14560484Sobrien vga_grborder, 14677298Sobrien (vr_draw_t *)vga_nop, 14760484Sobrien (vr_set_cursor_t *)vga_nop, 14860484Sobrien (vr_draw_cursor_t *)vga_nop, 14960484Sobrien (vr_blink_cursor_t *)vga_nop, 15060484Sobrien (vr_set_mouse_t *)vga_nop, 15160484Sobrien (vr_draw_mouse_t *)vga_nop, 15260484Sobrien}; 15360484SobrienRENDERER(cga, GRAPHICS_MODE, grrndrsw, vga_set); 15460484SobrienRENDERER(ega, GRAPHICS_MODE, grrndrsw, vga_set); 15560484SobrienRENDERER(vga, GRAPHICS_MODE, grrndrsw, vga_set); 15660484Sobrien#endif /* SC_NO_MODE_CHANGE */ 15760484Sobrien 15860484SobrienRENDERER_MODULE(vga, vga_set); 15960484Sobrien 16060484Sobrien#ifndef SC_NO_CUTPASTE 16160484Sobrien#if !defined(SC_ALT_MOUSE_IMAGE) || defined(SC_PIXEL_MODE) 16260484Sobrienstatic u_short mouse_and_mask[16] = { 16360484Sobrien 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 16460484Sobrien 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000 16560484Sobrien}; 16660484Sobrienstatic u_short mouse_or_mask[16] = { 16760484Sobrien 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800, 16860484Sobrien 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000 16960484Sobrien}; 17060484Sobrien#endif 17160484Sobrien#endif 17260484Sobrien 17360484Sobrien#ifdef SC_PIXEL_MODE 17460484Sobrien#define VIDEO_MEMORY_POS(scp, pos, x) \ 17560484Sobrien scp->sc->adp->va_window + \ 17660484Sobrien x * scp->xoff + \ 17760484Sobrien scp->yoff * scp->font_size * scp->sc->adp->va_line_width + \ 17860484Sobrien x * (pos % scp->xsize) + \ 17960484Sobrien scp->font_size * scp->sc->adp->va_line_width * (pos / scp->xsize) 18060484Sobrien 18160484Sobrien#define vga_drawpxl(pos, color) \ 18260484Sobrien switch (scp->sc->adp->va_info.vi_depth) { \ 18360484Sobrien case 32: \ 18460484Sobrien writel(pos, vga_palette32[color]); \ 18560484Sobrien break; \ 18660484Sobrien case 24: \ 18760484Sobrien if (((pos) & 1) == 0) { \ 18860484Sobrien writew(pos, vga_palette32[color]); \ 18960484Sobrien writeb(pos + 2, vga_palette32[color] >> 16);\ 19060484Sobrien } else { \ 19160484Sobrien writeb(pos, vga_palette32[color]); \ 19260484Sobrien writew(pos + 1, vga_palette32[color] >> 8);\ 19360484Sobrien } \ 19460484Sobrien break; \ 19560484Sobrien case 16: \ 19660484Sobrien if (scp->sc->adp->va_info.vi_pixel_fsizes[1] == 5)\ 19760484Sobrien writew(pos, vga_palette15[color]); \ 19860484Sobrien else \ 19960484Sobrien writew(pos, vga_palette16[color]); \ 20060484Sobrien break; \ 20160484Sobrien case 15: \ 20260484Sobrien writew(pos, vga_palette15[color]); \ 20360484Sobrien break; \ 20460484Sobrien case 8: \ 20560484Sobrien writeb(pos, (uint8_t)color); \ 20660484Sobrien } 20760484Sobrien 20860484Sobrienstatic uint32_t vga_palette32[16] = { 20960484Sobrien 0x000000, 0x0000ad, 0x00ad00, 0x00adad, 21060484Sobrien 0xad0000, 0xad00ad, 0xad5200, 0xadadad, 21160484Sobrien 0x525252, 0x5252ff, 0x52ff52, 0x52ffff, 21260484Sobrien 0xff5252, 0xff52ff, 0xffff52, 0xffffff 21360484Sobrien}; 21460484Sobrien 21560484Sobrienstatic uint16_t vga_palette16[16] = { 21660484Sobrien 0x0000, 0x0016, 0x0560, 0x0576, 0xb000, 0xb016, 0xb2a0, 0xb576, 21760484Sobrien 0x52aa, 0x52bf, 0x57ea, 0x57ff, 0xfaaa, 0xfabf, 0xffea, 0xffff 21860484Sobrien}; 21960484Sobrien 22060484Sobrienstatic uint16_t vga_palette15[16] = { 22160484Sobrien 0x0000, 0x0016, 0x02c0, 0x02d6, 0x5800, 0x5816, 0x5940, 0x5ad6, 22260484Sobrien 0x294a, 0x295f, 0x2bea, 0x2bff, 0x7d4a, 0x7d5f, 0x7fea, 0x7fff 22360484Sobrien}; 22460484Sobrien 22560484Sobrien#ifndef SC_NO_CUTPASTE 22660484Sobrienstatic uint32_t mouse_buf32[256]; 22760484Sobrienstatic uint16_t mouse_buf16[256]; 22860484Sobrienstatic uint8_t mouse_buf8[256]; 22960484Sobrien#endif 23060484Sobrien#endif 23160484Sobrien 23260484Sobrienstatic void 23360484Sobrienvga_nop(scr_stat *scp) 23460484Sobrien{ 23560484Sobrien} 23660484Sobrien 23760484Sobrien/* text mode renderer */ 23860484Sobrien 23977298Sobrienstatic void 24060484Sobrienvga_txtclear(scr_stat *scp, int c, int attr) 24160484Sobrien{ 24260484Sobrien sc_vtb_clear(&scp->scr, c, attr); 24360484Sobrien} 24460484Sobrien 24560484Sobrienstatic void 24660484Sobrienvga_txtborder(scr_stat *scp, int color) 24760484Sobrien{ 24860484Sobrien vidd_set_border(scp->sc->adp, color); 24960484Sobrien} 25060484Sobrien 25160484Sobrienstatic void 25260484Sobrienvga_txtdraw(scr_stat *scp, int from, int count, int flip) 25360484Sobrien{ 25460484Sobrien vm_offset_t p; 25560484Sobrien int c; 25660484Sobrien int a; 25760484Sobrien 25860484Sobrien if (from + count > scp->xsize*scp->ysize) 25960484Sobrien count = scp->xsize*scp->ysize - from; 26060484Sobrien 26160484Sobrien if (flip) { 26260484Sobrien for (p = sc_vtb_pointer(&scp->scr, from); count-- > 0; ++from) { 26360484Sobrien c = sc_vtb_getc(&scp->vtb, from); 26460484Sobrien a = sc_vtb_geta(&scp->vtb, from); 26560484Sobrien a = (a & 0x8800) | ((a & 0x7000) >> 4) 26660484Sobrien | ((a & 0x0700) << 4); 26760484Sobrien p = sc_vtb_putchar(&scp->scr, p, c, a); 26860484Sobrien } 26960484Sobrien } else { 27060484Sobrien sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count); 27160484Sobrien } 27277298Sobrien} 27360484Sobrien 27460484Sobrienstatic void 27560484Sobrienvga_txtcursor_shape(scr_stat *scp, int base, int height, int blink) 27660484Sobrien{ 27760484Sobrien if (base < 0 || base >= scp->font_size) 27860484Sobrien return; 27960484Sobrien /* the caller may set height <= 0 in order to disable the cursor */ 28060484Sobrien#if 0 28160484Sobrien scp->curs_attr.base = base; 28260484Sobrien scp->curs_attr.height = height; 28360484Sobrien#endif 28460484Sobrien vidd_set_hw_cursor_shape(scp->sc->adp, base, height, 28560484Sobrien scp->font_size, blink); 28660484Sobrien} 28760484Sobrien 28860484Sobrienstatic void 28960484Sobriendraw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip) 29060484Sobrien{ 29160484Sobrien sc_softc_t *sc; 29260484Sobrien 29360484Sobrien sc = scp->sc; 29460484Sobrien scp->cursor_saveunder_char = c; 29560484Sobrien scp->cursor_saveunder_attr = a; 29660484Sobrien 29760484Sobrien#ifndef SC_NO_FONT_LOADING 29860484Sobrien if (scp->curs_attr.flags & CONS_CHAR_CURSOR) { 29960484Sobrien unsigned char *font; 30060484Sobrien int h; 30160484Sobrien int i; 30260484Sobrien 30360484Sobrien if (scp->font_size < 14) { 30477298Sobrien font = sc->font_8; 30560484Sobrien h = 8; 30660484Sobrien } else if (scp->font_size >= 16) { 30760484Sobrien font = sc->font_16; 30860484Sobrien h = 16; 30960484Sobrien } else { 31060484Sobrien font = sc->font_14; 31160484Sobrien h = 14; 31260484Sobrien } 31360484Sobrien if (scp->curs_attr.base >= h) 31460484Sobrien return; 31560484Sobrien if (flip) 31660484Sobrien a = (a & 0x8800) 31760484Sobrien | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4); 31860484Sobrien bcopy(font + c*h, font + sc->cursor_char*h, h); 31977298Sobrien font = font + sc->cursor_char*h; 32060484Sobrien for (i = imax(h - scp->curs_attr.base - scp->curs_attr.height, 0); 32160484Sobrien i < h - scp->curs_attr.base; ++i) { 32260484Sobrien font[i] ^= 0xff; 32360484Sobrien } 32460484Sobrien /* XXX */ 32560484Sobrien vidd_load_font(sc->adp, 0, h, 8, font, sc->cursor_char, 1); 32660484Sobrien sc_vtb_putc(&scp->scr, at, sc->cursor_char, a); 32760484Sobrien } else 32860484Sobrien#endif /* SC_NO_FONT_LOADING */ 32960484Sobrien { 33060484Sobrien if ((a & 0x7000) == 0x7000) { 33160484Sobrien a &= 0x8f00; 33260484Sobrien if ((a & 0x0700) == 0) 33360484Sobrien a |= 0x0700; 33477298Sobrien } else { 33560484Sobrien a |= 0x7000; 33660484Sobrien if ((a & 0x0700) == 0x0700) 33760484Sobrien a &= 0xf000; 33860484Sobrien } 33960484Sobrien if (flip) 34060484Sobrien a = (a & 0x8800) 34160484Sobrien | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4); 34260484Sobrien sc_vtb_putc(&scp->scr, at, c, a); 34360484Sobrien } 34460484Sobrien} 34560484Sobrien 34660484Sobrienstatic void 34760484Sobrienvga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip) 34860484Sobrien{ 34960484Sobrien video_adapter_t *adp; 35060484Sobrien int cursor_attr; 35177298Sobrien 35260484Sobrien if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 35360484Sobrien return; 35460484Sobrien 35560484Sobrien adp = scp->sc->adp; 35660484Sobrien if (blink) { 35760484Sobrien scp->status |= VR_CURSOR_BLINK; 35860484Sobrien if (on) { 35960484Sobrien scp->status |= VR_CURSOR_ON; 36060484Sobrien vidd_set_hw_cursor(adp, at%scp->xsize, 36160484Sobrien at/scp->xsize); 36260484Sobrien } else { 36360484Sobrien if (scp->status & VR_CURSOR_ON) 36460484Sobrien vidd_set_hw_cursor(adp, -1, -1); 36560484Sobrien scp->status &= ~VR_CURSOR_ON; 36660484Sobrien } 36760484Sobrien } else { 36860484Sobrien scp->status &= ~VR_CURSOR_BLINK; 36960484Sobrien if (on) { 37060484Sobrien scp->status |= VR_CURSOR_ON; 37160484Sobrien draw_txtcharcursor(scp, at, 37260484Sobrien sc_vtb_getc(&scp->scr, at), 37360484Sobrien sc_vtb_geta(&scp->scr, at), 37460484Sobrien flip); 37560484Sobrien } else { 37660484Sobrien cursor_attr = scp->cursor_saveunder_attr; 37760484Sobrien if (flip) 37860484Sobrien cursor_attr = (cursor_attr & 0x8800) 37960484Sobrien | ((cursor_attr & 0x7000) >> 4) 38060484Sobrien | ((cursor_attr & 0x0700) << 4); 38160484Sobrien if (scp->status & VR_CURSOR_ON) 38260484Sobrien sc_vtb_putc(&scp->scr, at, 38360484Sobrien scp->cursor_saveunder_char, 38460484Sobrien cursor_attr); 38560484Sobrien scp->status &= ~VR_CURSOR_ON; 38660484Sobrien } 38760484Sobrien } 38860484Sobrien} 38960484Sobrien 39060484Sobrienstatic void 39160484Sobrienvga_txtblink(scr_stat *scp, int at, int flip) 39260484Sobrien{ 39360484Sobrien} 39460484Sobrien 39560484Sobrien#ifndef SC_NO_CUTPASTE 39660484Sobrien 39760484Sobrienstatic void 39860484Sobriendraw_txtmouse(scr_stat *scp, int x, int y) 39960484Sobrien{ 40060484Sobrien#ifndef SC_ALT_MOUSE_IMAGE 40160484Sobrien if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) { 40260484Sobrien u_char font_buf[128]; 40360484Sobrien u_short cursor[32]; 40460484Sobrien u_char c; 40560484Sobrien int pos; 40660484Sobrien int xoffset, yoffset; 40760484Sobrien int crtc_addr; 40860484Sobrien int i; 40960484Sobrien 41060484Sobrien /* prepare mousepointer char's bitmaps */ 41160484Sobrien pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 41260484Sobrien bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size, 41360484Sobrien &font_buf[0], scp->font_size); 41460484Sobrien bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size, 41560484Sobrien &font_buf[32], scp->font_size); 41660484Sobrien bcopy(scp->font 41760484Sobrien + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size, 41860484Sobrien &font_buf[64], scp->font_size); 41960484Sobrien bcopy(scp->font 42060484Sobrien + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size, 42160484Sobrien &font_buf[96], scp->font_size); 42260484Sobrien for (i = 0; i < scp->font_size; ++i) { 42360484Sobrien cursor[i] = font_buf[i]<<8 | font_buf[i+32]; 42460484Sobrien cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96]; 42560484Sobrien } 42660484Sobrien 42760484Sobrien /* now and-or in the mousepointer image */ 42860484Sobrien xoffset = x%8; 42960484Sobrien yoffset = y%scp->font_size; 43060484Sobrien for (i = 0; i < 16; ++i) { 43160484Sobrien cursor[i + yoffset] = 43260484Sobrien (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset)) 43360484Sobrien | (mouse_or_mask[i] >> xoffset); 43460484Sobrien } 43560484Sobrien for (i = 0; i < scp->font_size; ++i) { 43660484Sobrien font_buf[i] = (cursor[i] & 0xff00) >> 8; 43760484Sobrien font_buf[i + 32] = cursor[i] & 0xff; 43860484Sobrien font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8; 43960484Sobrien font_buf[i + 96] = cursor[i + scp->font_size] & 0xff; 44060484Sobrien } 44160484Sobrien 44260484Sobrien#if 1 44360484Sobrien /* wait for vertical retrace to avoid jitter on some videocards */ 44460484Sobrien crtc_addr = scp->sc->adp->va_crtc_addr; 44560484Sobrien while (!(inb(crtc_addr + 6) & 0x08)) /* idle */ ; 44660484Sobrien#endif 44760484Sobrien c = scp->sc->mouse_char; 44860484Sobrien vidd_load_font(scp->sc->adp, 0, 32, 8, font_buf, c, 4); 44960484Sobrien 45060484Sobrien sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos)); 45160484Sobrien /* FIXME: may be out of range! */ 45260484Sobrien sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2, 45360484Sobrien sc_vtb_geta(&scp->scr, pos + scp->xsize)); 45460484Sobrien if (x < (scp->xsize - 1)*8) { 45560484Sobrien sc_vtb_putc(&scp->scr, pos + 1, c + 1, 45660484Sobrien sc_vtb_geta(&scp->scr, pos + 1)); 45760484Sobrien sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3, 45860484Sobrien sc_vtb_geta(&scp->scr, pos + scp->xsize + 1)); 45960484Sobrien } 46060484Sobrien } else 46160484Sobrien#endif /* SC_ALT_MOUSE_IMAGE */ 46260484Sobrien { 46360484Sobrien /* Red, magenta and brown are mapped to green to to keep it readable */ 46460484Sobrien static const int col_conv[16] = { 46560484Sobrien 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14 46660484Sobrien }; 46760484Sobrien int pos; 46860484Sobrien int color; 46960484Sobrien int a; 47060484Sobrien 47160484Sobrien pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; 47260484Sobrien a = sc_vtb_geta(&scp->scr, pos); 47360484Sobrien if (scp->sc->adp->va_flags & V_ADP_COLOR) 47460484Sobrien color = (col_conv[(a & 0xf000) >> 12] << 12) 47560484Sobrien | ((a & 0x0f00) | 0x0800); 47660484Sobrien else 47760484Sobrien color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4); 47860484Sobrien sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color); 47960484Sobrien } 48060484Sobrien} 48160484Sobrien 48260484Sobrienstatic void 48360484Sobrienremove_txtmouse(scr_stat *scp, int x, int y) 48460484Sobrien{ 48560484Sobrien} 48660484Sobrien 48760484Sobrienstatic void 48860484Sobrienvga_txtmouse(scr_stat *scp, int x, int y, int on) 48960484Sobrien{ 49060484Sobrien if (on) 49160484Sobrien draw_txtmouse(scp, x, y); 49260484Sobrien else 49360484Sobrien remove_txtmouse(scp, x, y); 49460484Sobrien} 49560484Sobrien 49660484Sobrien#endif /* SC_NO_CUTPASTE */ 49760484Sobrien 49860484Sobrien#ifdef SC_PIXEL_MODE 49960484Sobrien 50060484Sobrien/* pixel (raster text) mode renderer */ 50160484Sobrien 50260484Sobrienstatic void 50360484Sobrienvga_rndrinit(scr_stat *scp) 50460484Sobrien{ 50560484Sobrien if (scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_PLANAR) { 50660484Sobrien scp->rndr->clear = vga_pxlclear_planar; 50760484Sobrien scp->rndr->draw_border = vga_pxlborder_planar; 50860484Sobrien scp->rndr->draw = vga_vgadraw_planar; 50960484Sobrien scp->rndr->draw_cursor = vga_pxlcursor_planar; 51060484Sobrien scp->rndr->blink_cursor = vga_pxlblink_planar; 51160484Sobrien scp->rndr->draw_mouse = vga_pxlmouse_planar; 51260484Sobrien } else 51360484Sobrien if (scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_DIRECT || 51460484Sobrien scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_PACKED) { 51560484Sobrien scp->rndr->clear = vga_pxlclear_direct; 51660484Sobrien scp->rndr->draw_border = vga_pxlborder_direct; 51760484Sobrien scp->rndr->draw = vga_vgadraw_direct; 51860484Sobrien scp->rndr->draw_cursor = vga_pxlcursor_direct; 51960484Sobrien scp->rndr->blink_cursor = vga_pxlblink_direct; 52060484Sobrien scp->rndr->draw_mouse = vga_pxlmouse_direct; 52160484Sobrien } 52260484Sobrien} 52360484Sobrien 52460484Sobrienstatic void 52560484Sobrienvga_pxlclear_direct(scr_stat *scp, int c, int attr) 52660484Sobrien{ 52760484Sobrien vm_offset_t p; 52860484Sobrien int line_width; 52960484Sobrien int pixel_size; 53060484Sobrien int lines; 53160484Sobrien int i; 53260484Sobrien 53360484Sobrien line_width = scp->sc->adp->va_line_width; 53460484Sobrien pixel_size = scp->sc->adp->va_info.vi_pixel_size; 53560484Sobrien lines = scp->ysize * scp->font_size; 53660484Sobrien p = scp->sc->adp->va_window + 53760484Sobrien line_width * scp->yoff * scp->font_size + 53860484Sobrien scp->xoff * 8 * pixel_size; 53960484Sobrien 54060484Sobrien for (i = 0; i < lines; ++i) { 54160484Sobrien bzero_io((void *)p, scp->xsize * 8 * pixel_size); 54260484Sobrien p += line_width; 54360484Sobrien } 54460484Sobrien} 54560484Sobrien 54660484Sobrienstatic void 54760484Sobrienvga_pxlclear_planar(scr_stat *scp, int c, int attr) 54860484Sobrien{ 54960484Sobrien vm_offset_t p; 55060484Sobrien int line_width; 55160484Sobrien int lines; 55260484Sobrien int i; 55360484Sobrien 55460484Sobrien /* XXX: we are just filling the screen with the background color... */ 55560484Sobrien outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 55660484Sobrien outw(GDCIDX, 0x0003); /* data rotate/function select */ 55760484Sobrien outw(GDCIDX, 0x0f01); /* set/reset enable */ 55860484Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 55960484Sobrien outw(GDCIDX, ((attr & 0xf000) >> 4) | 0x00); /* set/reset */ 56060484Sobrien line_width = scp->sc->adp->va_line_width; 56160484Sobrien lines = scp->ysize*scp->font_size; 56260484Sobrien p = scp->sc->adp->va_window + line_width*scp->yoff*scp->font_size 56360484Sobrien + scp->xoff; 56460484Sobrien for (i = 0; i < lines; ++i) { 56560484Sobrien bzero_io((void *)p, scp->xsize); 56660484Sobrien p += line_width; 56760484Sobrien } 56860484Sobrien outw(GDCIDX, 0x0000); /* set/reset */ 56960484Sobrien outw(GDCIDX, 0x0001); /* set/reset enable */ 57060484Sobrien} 57160484Sobrien 57260484Sobrienstatic void 57360484Sobrienvga_pxlborder_direct(scr_stat *scp, int color) 57460484Sobrien{ 57560484Sobrien vm_offset_t s; 57660484Sobrien vm_offset_t e; 57760484Sobrien vm_offset_t f; 57877298Sobrien int line_width; 57960484Sobrien int pixel_size; 58060484Sobrien int x; 58160484Sobrien int y; 58260484Sobrien int i; 58360484Sobrien 58460484Sobrien line_width = scp->sc->adp->va_line_width; 58560484Sobrien pixel_size = scp->sc->adp->va_info.vi_pixel_size; 58660484Sobrien 58760484Sobrien if (scp->yoff > 0) { 58860484Sobrien s = scp->sc->adp->va_window; 58960484Sobrien e = s + line_width * scp->yoff * scp->font_size; 59060484Sobrien 59160484Sobrien for (f = s; f < e; f += pixel_size) 59260484Sobrien vga_drawpxl(f, color); 59360484Sobrien } 59477298Sobrien 59560484Sobrien y = (scp->yoff + scp->ysize) * scp->font_size; 59660484Sobrien 59760484Sobrien if (scp->ypixel > y) { 59860484Sobrien s = scp->sc->adp->va_window + line_width * y; 59960484Sobrien e = s + line_width * (scp->ypixel - y); 60060484Sobrien 60160484Sobrien for (f = s; f < e; f += pixel_size) 60260484Sobrien vga_drawpxl(f, color); 60360484Sobrien } 60460484Sobrien 60560484Sobrien y = scp->yoff * scp->font_size; 60660484Sobrien x = scp->xpixel / 8 - scp->xoff - scp->xsize; 60760484Sobrien 60860484Sobrien for (i = 0; i < scp->ysize * scp->font_size; ++i) { 60960484Sobrien if (scp->xoff > 0) { 61060484Sobrien s = scp->sc->adp->va_window + line_width * (y + i); 61160484Sobrien e = s + scp->xoff * 8 * pixel_size; 61260484Sobrien 61360484Sobrien for (f = s; f < e; f += pixel_size) 61460484Sobrien vga_drawpxl(f, color); 61560484Sobrien } 61660484Sobrien 61760484Sobrien if (x > 0) { 61860484Sobrien s = scp->sc->adp->va_window + line_width * (y + i) + 61960484Sobrien scp->xoff * 8 * pixel_size + 62060484Sobrien scp->xsize * 8 * pixel_size; 62160484Sobrien e = s + x * 8 * pixel_size; 62260484Sobrien 62360484Sobrien for (f = s; f < e; f += pixel_size) 62460484Sobrien vga_drawpxl(f, color); 62560484Sobrien } 62660484Sobrien } 62760484Sobrien} 62860484Sobrien 62960484Sobrienstatic void 63060484Sobrienvga_pxlborder_planar(scr_stat *scp, int color) 63160484Sobrien{ 63260484Sobrien vm_offset_t p; 63360484Sobrien int line_width; 63460484Sobrien int x; 63560484Sobrien int y; 63660484Sobrien int i; 63760484Sobrien 63860484Sobrien vidd_set_border(scp->sc->adp, color); 63960484Sobrien 64060484Sobrien outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 64160484Sobrien outw(GDCIDX, 0x0003); /* data rotate/function select */ 64260484Sobrien outw(GDCIDX, 0x0f01); /* set/reset enable */ 64360484Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 64460484Sobrien outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ 64560484Sobrien line_width = scp->sc->adp->va_line_width; 64660484Sobrien p = scp->sc->adp->va_window; 64760484Sobrien if (scp->yoff > 0) 64860484Sobrien bzero_io((void *)p, line_width*scp->yoff*scp->font_size); 64960484Sobrien y = (scp->yoff + scp->ysize)*scp->font_size; 65060484Sobrien if (scp->ypixel > y) 65160484Sobrien bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y)); 65260484Sobrien y = scp->yoff*scp->font_size; 65360484Sobrien x = scp->xpixel/8 - scp->xoff - scp->xsize; 65460484Sobrien for (i = 0; i < scp->ysize*scp->font_size; ++i) { 65560484Sobrien if (scp->xoff > 0) 65660484Sobrien bzero_io((void *)(p + line_width*(y + i)), scp->xoff); 65760484Sobrien if (x > 0) 65860484Sobrien bzero_io((void *)(p + line_width*(y + i) 65960484Sobrien + scp->xoff + scp->xsize), x); 66060484Sobrien } 66160484Sobrien outw(GDCIDX, 0x0000); /* set/reset */ 66260484Sobrien outw(GDCIDX, 0x0001); /* set/reset enable */ 66360484Sobrien} 66460484Sobrien 66560484Sobrienstatic void 66660484Sobrienvga_egadraw(scr_stat *scp, int from, int count, int flip) 66760484Sobrien{ 66860484Sobrien vm_offset_t d; 66960484Sobrien vm_offset_t e; 67060484Sobrien u_char *f; 67160484Sobrien u_short bg; 67260484Sobrien u_short col1, col2; 67377298Sobrien int line_width; 67460484Sobrien int i, j; 67560484Sobrien int a; 67660484Sobrien u_char c; 67760484Sobrien 67860484Sobrien line_width = scp->sc->adp->va_line_width; 67960484Sobrien 68060484Sobrien d = VIDEO_MEMORY_POS(scp, from, 1); 68160484Sobrien 68260484Sobrien outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 68360484Sobrien outw(GDCIDX, 0x0003); /* data rotate/function select */ 68460484Sobrien outw(GDCIDX, 0x0f01); /* set/reset enable */ 68560484Sobrien bg = -1; 68660484Sobrien if (from + count > scp->xsize*scp->ysize) 68760484Sobrien count = scp->xsize*scp->ysize - from; 68877298Sobrien for (i = from; count-- > 0; ++i) { 68960484Sobrien a = sc_vtb_geta(&scp->vtb, i); 69060484Sobrien if (flip) { 69160484Sobrien col1 = ((a & 0x7000) >> 4) | (a & 0x0800); 69260484Sobrien col2 = ((a & 0x8000) >> 4) | (a & 0x0700); 69360484Sobrien } else { 69460484Sobrien col1 = (a & 0x0f00); 69560484Sobrien col2 = (a & 0xf000) >> 4; 69660484Sobrien } 69760484Sobrien /* set background color in EGA/VGA latch */ 69860484Sobrien if (bg != col2) { 69960484Sobrien bg = col2; 70060484Sobrien outw(GDCIDX, bg | 0x00); /* set/reset */ 70160484Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 70260484Sobrien writeb(d, 0); 70377298Sobrien c = readb(d); /* set bg color in the latch */ 70460484Sobrien } 70560484Sobrien /* foreground color */ 70660484Sobrien outw(GDCIDX, col1 | 0x00); /* set/reset */ 70760484Sobrien e = d; 70860484Sobrien f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]); 70960484Sobrien for (j = 0; j < scp->font_size; ++j, ++f) { 71060484Sobrien outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */ 71160484Sobrien writeb(e, 0); 71260484Sobrien e += line_width; 71360484Sobrien } 71460484Sobrien ++d; 71560484Sobrien if ((i % scp->xsize) == scp->xsize - 1) 71660484Sobrien d += scp->xoff*2 71760484Sobrien + (scp->font_size - 1)*line_width; 71877298Sobrien } 71960484Sobrien outw(GDCIDX, 0x0000); /* set/reset */ 72060484Sobrien outw(GDCIDX, 0x0001); /* set/reset enable */ 72160484Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 72260484Sobrien} 72360484Sobrien 72460484Sobrienstatic void 72560484Sobrienvga_vgadraw_direct(scr_stat *scp, int from, int count, int flip) 72660484Sobrien{ 72760484Sobrien vm_offset_t d = 0; 72860484Sobrien vm_offset_t e; 72960484Sobrien u_char *f; 73060484Sobrien u_short col1, col2, color; 73160484Sobrien int line_width, pixel_size; 73260484Sobrien int i, j, k; 73360484Sobrien int a; 73460484Sobrien 73560484Sobrien line_width = scp->sc->adp->va_line_width; 73660484Sobrien pixel_size = scp->sc->adp->va_info.vi_pixel_size; 73760484Sobrien 73860484Sobrien d = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size); 73960484Sobrien 74060484Sobrien if (from + count > scp->xsize * scp->ysize) 74160484Sobrien count = scp->xsize * scp->ysize - from; 74260484Sobrien 74360484Sobrien for (i = from; count-- > 0; ++i) { 74460484Sobrien a = sc_vtb_geta(&scp->vtb, i); 74560484Sobrien 74660484Sobrien if (flip) { 74760484Sobrien col1 = (((a & 0x7000) >> 4) | (a & 0x0800)) >> 8; 74860484Sobrien col2 = (((a & 0x8000) >> 4) | (a & 0x0700)) >> 8; 74960484Sobrien } else { 75060484Sobrien col1 = (a & 0x0f00) >> 8; 75160484Sobrien col2 = (a & 0xf000) >> 12; 75260484Sobrien } 75360484Sobrien 75460484Sobrien e = d; 75560484Sobrien f = &(scp->font[sc_vtb_getc(&scp->vtb, i) * scp->font_size]); 75660484Sobrien 75760484Sobrien for (j = 0; j < scp->font_size; ++j, ++f) { 75860484Sobrien for (k = 0; k < 8; ++k) { 75960484Sobrien color = *f & (1 << (7 - k)) ? col1 : col2; 76060484Sobrien vga_drawpxl(e + pixel_size * k, color); 76160484Sobrien } 76260484Sobrien 76360484Sobrien e += line_width; 76460484Sobrien } 76560484Sobrien 76660484Sobrien d += 8 * pixel_size; 76760484Sobrien 76860484Sobrien if ((i % scp->xsize) == scp->xsize - 1) 76960484Sobrien d += scp->xoff * 16 * pixel_size + 77060484Sobrien (scp->font_size - 1) * line_width; 77160484Sobrien } 77260484Sobrien} 77360484Sobrien 77460484Sobrienstatic void 77560484Sobrienvga_vgadraw_planar(scr_stat *scp, int from, int count, int flip) 77660484Sobrien{ 77760484Sobrien vm_offset_t d; 77860484Sobrien vm_offset_t e; 77960484Sobrien u_char *f; 78060484Sobrien u_short bg; 78160484Sobrien u_short col1, col2; 78260484Sobrien int line_width; 78360484Sobrien int i, j; 78460484Sobrien int a; 78560484Sobrien u_char c; 78660484Sobrien 78760484Sobrien d = VIDEO_MEMORY_POS(scp, from, 1); 78860484Sobrien 78960484Sobrien line_width = scp->sc->adp->va_line_width; 79060484Sobrien 79160484Sobrien outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 79260484Sobrien outw(GDCIDX, 0x0003); /* data rotate/function select */ 79360484Sobrien outw(GDCIDX, 0x0f01); /* set/reset enable */ 79460484Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 79560484Sobrien bg = -1; 79660484Sobrien if (from + count > scp->xsize*scp->ysize) 79760484Sobrien count = scp->xsize*scp->ysize - from; 79860484Sobrien for (i = from; count-- > 0; ++i) { 79960484Sobrien a = sc_vtb_geta(&scp->vtb, i); 80060484Sobrien if (flip) { 80160484Sobrien col1 = ((a & 0x7000) >> 4) | (a & 0x0800); 80260484Sobrien col2 = ((a & 0x8000) >> 4) | (a & 0x0700); 80360484Sobrien } else { 80460484Sobrien col1 = (a & 0x0f00); 80560484Sobrien col2 = (a & 0xf000) >> 4; 80660484Sobrien } 80760484Sobrien /* set background color in EGA/VGA latch */ 80860484Sobrien if (bg != col2) { 80960484Sobrien bg = col2; 81060484Sobrien outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 81160484Sobrien outw(GDCIDX, bg | 0x00); /* set/reset */ 81260484Sobrien writeb(d, 0); 81360484Sobrien c = readb(d); /* set bg color in the latch */ 81460484Sobrien outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ 81560484Sobrien } 81660484Sobrien /* foreground color */ 81760484Sobrien outw(GDCIDX, col1 | 0x00); /* set/reset */ 81860484Sobrien e = d; 81960484Sobrien f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]); 82060484Sobrien for (j = 0; j < scp->font_size; ++j, ++f) { 82160484Sobrien writeb(e, *f); 82260484Sobrien e += line_width; 82360484Sobrien } 82460484Sobrien ++d; 82560484Sobrien if ((i % scp->xsize) == scp->xsize - 1) 82660484Sobrien d += scp->xoff*2 82760484Sobrien + (scp->font_size - 1)*line_width; 82860484Sobrien } 82960484Sobrien outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 83060484Sobrien outw(GDCIDX, 0x0000); /* set/reset */ 83160484Sobrien outw(GDCIDX, 0x0001); /* set/reset enable */ 83260484Sobrien} 83360484Sobrien 83460484Sobrienstatic void 83560484Sobrienvga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink) 83660484Sobrien{ 83760484Sobrien if (base < 0 || base >= scp->font_size) 83860484Sobrien return; 83960484Sobrien /* the caller may set height <= 0 in order to disable the cursor */ 84060484Sobrien#if 0 84160484Sobrien scp->curs_attr.base = base; 84260484Sobrien scp->curs_attr.height = height; 84360484Sobrien#endif 84460484Sobrien} 84560484Sobrien 84660484Sobrienstatic void 84760484Sobriendraw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip) 84860484Sobrien{ 84960484Sobrien vm_offset_t d = 0; 85060484Sobrien u_char *f; 85160484Sobrien int line_width, pixel_size; 85260484Sobrien int height; 85360484Sobrien int col1, col2, color; 85460484Sobrien int a; 85560484Sobrien int i, j; 85660484Sobrien 85760484Sobrien line_width = scp->sc->adp->va_line_width; 85860484Sobrien pixel_size = scp->sc->adp->va_info.vi_pixel_size; 85960484Sobrien 86060484Sobrien d = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) + 86160484Sobrien (scp->font_size - scp->curs_attr.base - 1) * line_width; 86260484Sobrien 86360484Sobrien a = sc_vtb_geta(&scp->vtb, at); 86460484Sobrien 86560484Sobrien if (flip) { 86660484Sobrien col1 = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8; 86760484Sobrien col2 = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8; 86860484Sobrien } else { 86960484Sobrien col1 = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8; 87060484Sobrien col2 = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8; 87160484Sobrien } 87260484Sobrien 87360484Sobrien f = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size + 87460484Sobrien scp->font_size - scp->curs_attr.base - 1]); 87560484Sobrien 87660484Sobrien height = imin(scp->curs_attr.height, scp->font_size); 87760484Sobrien 87860484Sobrien for (i = 0; i < height; ++i, --f) { 87960484Sobrien for (j = 0; j < 8; ++j) { 88060484Sobrien color = *f & (1 << (7 - j)) ? col1 : col2; 88160484Sobrien vga_drawpxl(d + pixel_size * j, color); 88260484Sobrien } 88360484Sobrien 88460484Sobrien d -= line_width; 88560484Sobrien } 88660484Sobrien} 88760484Sobrien 88860484Sobrienstatic void 88960484Sobriendraw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip) 89060484Sobrien{ 89160484Sobrien vm_offset_t d; 89260484Sobrien u_char *f; 89360484Sobrien int line_width; 89460484Sobrien int height; 89560484Sobrien int col; 89660484Sobrien int a; 89760484Sobrien int i; 89860484Sobrien u_char c; 89960484Sobrien 90060484Sobrien line_width = scp->sc->adp->va_line_width; 90160484Sobrien 90260484Sobrien d = VIDEO_MEMORY_POS(scp, at, 1) + 90360484Sobrien (scp->font_size - scp->curs_attr.base - 1) * line_width; 90460484Sobrien 90560484Sobrien outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 90660484Sobrien outw(GDCIDX, 0x0003); /* data rotate/function select */ 90760484Sobrien outw(GDCIDX, 0x0f01); /* set/reset enable */ 90860484Sobrien /* set background color in EGA/VGA latch */ 90960484Sobrien a = sc_vtb_geta(&scp->vtb, at); 91060484Sobrien if (flip) 91160484Sobrien col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); 91260484Sobrien else 91360484Sobrien col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); 91460484Sobrien outw(GDCIDX, col | 0x00); /* set/reset */ 91560484Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 91660484Sobrien writeb(d, 0); 91760484Sobrien c = readb(d); /* set bg color in the latch */ 91860484Sobrien /* foreground color */ 91960484Sobrien if (flip) 92060484Sobrien col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); 92160484Sobrien else 92260484Sobrien col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); 92360484Sobrien outw(GDCIDX, col | 0x00); /* set/reset */ 92460484Sobrien f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size 92560484Sobrien + scp->font_size - scp->curs_attr.base - 1]); 92660484Sobrien height = imin(scp->curs_attr.height, scp->font_size); 92760484Sobrien for (i = 0; i < height; ++i, --f) { 92860484Sobrien outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */ 92960484Sobrien writeb(d, 0); 93060484Sobrien d -= line_width; 93160484Sobrien } 93260484Sobrien outw(GDCIDX, 0x0000); /* set/reset */ 93360484Sobrien outw(GDCIDX, 0x0001); /* set/reset enable */ 93460484Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 93560484Sobrien} 93660484Sobrien 93760484Sobrienstatic int pxlblinkrate = 0; 93860484Sobrien 93960484Sobrienstatic void 94060484Sobrienvga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip) 94160484Sobrien{ 94260484Sobrien if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 94360484Sobrien return; 94460484Sobrien 94560484Sobrien if (on) { 94660484Sobrien if (!blink) { 94760484Sobrien scp->status |= VR_CURSOR_ON; 94860484Sobrien draw_pxlcursor_direct(scp, at, on, flip); 94960484Sobrien } else if (++pxlblinkrate & 4) { 95060484Sobrien pxlblinkrate = 0; 95160484Sobrien scp->status ^= VR_CURSOR_ON; 95260484Sobrien draw_pxlcursor_direct(scp, at, 95360484Sobrien scp->status & VR_CURSOR_ON, 95460484Sobrien flip); 95560484Sobrien } 95660484Sobrien } else { 95760484Sobrien if (scp->status & VR_CURSOR_ON) 95860484Sobrien draw_pxlcursor_direct(scp, at, on, flip); 95960484Sobrien scp->status &= ~VR_CURSOR_ON; 96077298Sobrien } 96160484Sobrien if (blink) 96260484Sobrien scp->status |= VR_CURSOR_BLINK; 96360484Sobrien else 96460484Sobrien scp->status &= ~VR_CURSOR_BLINK; 96560484Sobrien} 96660484Sobrien 96760484Sobrienstatic void 96860484Sobrienvga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip) 96960484Sobrien{ 97060484Sobrien if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 97160484Sobrien return; 97260484Sobrien 97360484Sobrien if (on) { 97460484Sobrien if (!blink) { 97577298Sobrien scp->status |= VR_CURSOR_ON; 97660484Sobrien draw_pxlcursor_planar(scp, at, on, flip); 97760484Sobrien } else if (++pxlblinkrate & 4) { 97860484Sobrien pxlblinkrate = 0; 97960484Sobrien scp->status ^= VR_CURSOR_ON; 98060484Sobrien draw_pxlcursor_planar(scp, at, 98160484Sobrien scp->status & VR_CURSOR_ON, 98260484Sobrien flip); 98360484Sobrien } 98460484Sobrien } else { 98560484Sobrien if (scp->status & VR_CURSOR_ON) 98660484Sobrien draw_pxlcursor_planar(scp, at, on, flip); 98760484Sobrien scp->status &= ~VR_CURSOR_ON; 98860484Sobrien } 98960484Sobrien if (blink) 99060484Sobrien scp->status |= VR_CURSOR_BLINK; 99177298Sobrien else 99277298Sobrien scp->status &= ~VR_CURSOR_BLINK; 99360484Sobrien} 99460484Sobrien 99560484Sobrienstatic void 99660484Sobrienvga_pxlblink_direct(scr_stat *scp, int at, int flip) 99777298Sobrien{ 99860484Sobrien if (!(scp->status & VR_CURSOR_BLINK)) 99960484Sobrien return; 100060484Sobrien if (!(++pxlblinkrate & 4)) 100160484Sobrien return; 100260484Sobrien pxlblinkrate = 0; 100377298Sobrien scp->status ^= VR_CURSOR_ON; 100477298Sobrien draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip); 100577298Sobrien} 100677298Sobrien 100760484Sobrienstatic void 100860484Sobrienvga_pxlblink_planar(scr_stat *scp, int at, int flip) 100960484Sobrien{ 101060484Sobrien if (!(scp->status & VR_CURSOR_BLINK)) 101160484Sobrien return; 101260484Sobrien if (!(++pxlblinkrate & 4)) 101360484Sobrien return; 101460484Sobrien pxlblinkrate = 0; 101560484Sobrien scp->status ^= VR_CURSOR_ON; 101660484Sobrien draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip); 101777298Sobrien} 101860484Sobrien 101960484Sobrien#ifndef SC_NO_CUTPASTE 102060484Sobrien 102160484Sobrienstatic void 102260484Sobriendraw_pxlmouse_planar(scr_stat *scp, int x, int y) 102360484Sobrien{ 102460484Sobrien vm_offset_t p; 102577298Sobrien int line_width; 102660484Sobrien int xoff, yoff; 102760484Sobrien int ymax; 102860484Sobrien u_short m; 102960484Sobrien int i, j; 103060484Sobrien 103177298Sobrien line_width = scp->sc->adp->va_line_width; 103260484Sobrien xoff = (x - scp->xoff*8)%8; 103360484Sobrien yoff = y - (y/line_width)*line_width; 103460484Sobrien ymax = imin(y + 16, scp->ypixel); 103560484Sobrien 103660484Sobrien outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */ 103760484Sobrien outw(GDCIDX, 0x0001); /* set/reset enable */ 103860484Sobrien outw(GDCIDX, 0x0002); /* color compare */ 103960484Sobrien outw(GDCIDX, 0x0007); /* color don't care */ 104077298Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 104160484Sobrien outw(GDCIDX, 0x0803); /* data rotate/function select (and) */ 104260484Sobrien p = scp->sc->adp->va_window + line_width*y + x/8; 104360484Sobrien if (x < scp->xpixel - 8) { 104460484Sobrien for (i = y, j = 0; i < ymax; ++i, ++j) { 104577298Sobrien m = ~(mouse_and_mask[j] >> xoff); 104660484Sobrien#if defined(__i386__) || defined(__amd64__) 104760484Sobrien *(u_char *)p &= m >> 8; 104860484Sobrien *(u_char *)(p + 1) &= m; 104960484Sobrien#else 105060484Sobrien writeb(p, readb(p) & (m >> 8)); 105177298Sobrien writeb(p + 1, readb(p + 1) & (m >> 8)); 105260484Sobrien#endif 105360484Sobrien p += line_width; 105460484Sobrien } 105560484Sobrien } else { 105677298Sobrien xoff += 8; 105760484Sobrien for (i = y, j = 0; i < ymax; ++i, ++j) { 105860484Sobrien m = ~(mouse_and_mask[j] >> xoff); 105960484Sobrien#if defined(__i386__) || defined(__amd64__) 106060484Sobrien *(u_char *)p &= m; 106160484Sobrien#else 106277298Sobrien writeb(p, readb(p) & (m >> 8)); 106377298Sobrien#endif 106460484Sobrien p += line_width; 106577298Sobrien } 106660484Sobrien } 106760484Sobrien outw(GDCIDX, 0x1003); /* data rotate/function select (or) */ 106877298Sobrien p = scp->sc->adp->va_window + line_width*y + x/8; 106960484Sobrien if (x < scp->xpixel - 8) { 107060484Sobrien for (i = y, j = 0; i < ymax; ++i, ++j) { 107177298Sobrien m = mouse_or_mask[j] >> xoff; 107260484Sobrien#if defined(__i386__) || defined(__amd64__) 107377298Sobrien *(u_char *)p &= m >> 8; 107460484Sobrien *(u_char *)(p + 1) &= m; 107577298Sobrien#else 107660484Sobrien writeb(p, readb(p) & (m >> 8)); 107760484Sobrien writeb(p + 1, readb(p + 1) & (m >> 8)); 107860484Sobrien#endif 107960484Sobrien p += line_width; 108060484Sobrien } 108160484Sobrien } else { 108260484Sobrien for (i = y, j = 0; i < ymax; ++i, ++j) { 108377298Sobrien m = mouse_or_mask[j] >> xoff; 108460484Sobrien#if defined(__i386__) || defined(__amd64__) 108560484Sobrien *(u_char *)p &= m; 108660484Sobrien#else 108777298Sobrien writeb(p, readb(p) & (m >> 8)); 108860484Sobrien#endif 108977298Sobrien p += line_width; 109060484Sobrien } 109160484Sobrien } 109277298Sobrien outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 109360484Sobrien outw(GDCIDX, 0x0003); /* data rotate/function select */ 109460484Sobrien} 109560484Sobrien 109660484Sobrienstatic void 109760484Sobrienremove_pxlmouse_planar(scr_stat *scp, int x, int y) 109877298Sobrien{ 109977298Sobrien vm_offset_t p; 110060484Sobrien int col, row; 110177298Sobrien int pos; 110260484Sobrien int line_width; 110360484Sobrien int ymax; 110460484Sobrien int i; 110560484Sobrien 110660484Sobrien /* erase the mouse cursor image */ 110777298Sobrien col = x/8 - scp->xoff; 110860484Sobrien row = y/scp->font_size - scp->yoff; 110960484Sobrien pos = row*scp->xsize + col; 111060484Sobrien i = (col < scp->xsize - 1) ? 2 : 1; 111160484Sobrien (*scp->rndr->draw)(scp, pos, i, FALSE); 111260484Sobrien if (row < scp->ysize - 1) 111377298Sobrien (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE); 111460484Sobrien 111560484Sobrien /* paint border if necessary */ 111660484Sobrien line_width = scp->sc->adp->va_line_width; 111760484Sobrien outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 111860484Sobrien outw(GDCIDX, 0x0003); /* data rotate/function select */ 111960484Sobrien outw(GDCIDX, 0x0f01); /* set/reset enable */ 112060484Sobrien outw(GDCIDX, 0xff08); /* bit mask */ 112177298Sobrien outw(GDCIDX, (scp->border << 8) | 0x00); /* set/reset */ 112260484Sobrien if (row == scp->ysize - 1) { 112360484Sobrien i = (scp->ysize + scp->yoff)*scp->font_size; 112460484Sobrien ymax = imin(i + scp->font_size, scp->ypixel); 112560484Sobrien p = scp->sc->adp->va_window + i*line_width + scp->xoff + col; 112660484Sobrien if (col < scp->xsize - 1) { 112760484Sobrien for (; i < ymax; ++i) { 112860484Sobrien writeb(p, 0); 112960484Sobrien writeb(p + 1, 0); 113060484Sobrien p += line_width; 113160484Sobrien } 113260484Sobrien } else { 113360484Sobrien for (; i < ymax; ++i) { 113460484Sobrien writeb(p, 0); 113560484Sobrien p += line_width; 113660484Sobrien } 113777298Sobrien } 113860484Sobrien } 113960484Sobrien if ((col == scp->xsize - 1) && (scp->xoff > 0)) { 114060484Sobrien i = (row + scp->yoff)*scp->font_size; 114160484Sobrien ymax = imin(i + scp->font_size*2, scp->ypixel); 114260484Sobrien p = scp->sc->adp->va_window + i*line_width 114360484Sobrien + scp->xoff + scp->xsize; 114460484Sobrien for (; i < ymax; ++i) { 114560484Sobrien writeb(p, 0); 114660484Sobrien p += line_width; 114760484Sobrien } 114860484Sobrien } 114960484Sobrien outw(GDCIDX, 0x0000); /* set/reset */ 115077298Sobrien outw(GDCIDX, 0x0001); /* set/reset enable */ 115160484Sobrien} 115260484Sobrien 115360484Sobrienstatic void 115460484Sobrienvga_pxlmouse_direct(scr_stat *scp, int x, int y, int on) 115560484Sobrien{ 115660484Sobrien vm_offset_t p; 115760484Sobrien int line_width, pixel_size; 115860484Sobrien int xend, yend; 115960484Sobrien static int x_old = 0, xend_old = 0; 116060484Sobrien static int y_old = 0, yend_old = 0; 116160484Sobrien int i, j; 116260484Sobrien uint32_t *u32; 116360484Sobrien uint16_t *u16; 116460484Sobrien uint8_t *u8; 116560484Sobrien int bpp; 116660484Sobrien 116760484Sobrien if (!on) 116860484Sobrien return; 116960484Sobrien 117060484Sobrien bpp = scp->sc->adp->va_info.vi_depth; 117177298Sobrien 117260484Sobrien if ((bpp == 16) && (scp->sc->adp->va_info.vi_pixel_fsizes[1] == 5)) 117360484Sobrien bpp = 15; 117460484Sobrien 117560484Sobrien line_width = scp->sc->adp->va_line_width; 117660484Sobrien pixel_size = scp->sc->adp->va_info.vi_pixel_size; 117760484Sobrien 117860484Sobrien xend = imin(x + 16, scp->xpixel); 117960484Sobrien yend = imin(y + 16, scp->ypixel); 118060484Sobrien 118160484Sobrien p = scp->sc->adp->va_window + y_old * line_width + x_old * pixel_size; 118260484Sobrien 118360484Sobrien for (i = 0; i < (yend_old - y_old); i++) { 118477298Sobrien for (j = (xend_old - x_old - 1); j >= 0; j--) { 118560484Sobrien switch (bpp) { 118660484Sobrien case 32: 118760484Sobrien u32 = (uint32_t*)(p + j * pixel_size); 118860484Sobrien writel(u32, mouse_buf32[i * 16 + j]); 118960484Sobrien break; 119060484Sobrien case 16: 119160484Sobrien /* FALLTHROUGH */ 119260484Sobrien case 15: 119360484Sobrien u16 = (uint16_t*)(p + j * pixel_size); 119460484Sobrien writew(u16, mouse_buf16[i * 16 + j]); 119560484Sobrien break; 119660484Sobrien case 8: 119760484Sobrien u8 = (uint8_t*)(p + j * pixel_size); 119860484Sobrien writeb(u8, mouse_buf8[i * 16 + j]); 119960484Sobrien break; 120060484Sobrien } 120160484Sobrien } 120260484Sobrien 120360484Sobrien p += line_width; 120460484Sobrien } 120560484Sobrien 120660484Sobrien p = scp->sc->adp->va_window + y * line_width + x * pixel_size; 120760484Sobrien 120860484Sobrien for (i = 0; i < (yend - y); i++) { 120960484Sobrien for (j = (xend - x - 1); j >= 0; j--) { 121060484Sobrien switch (bpp) { 121160484Sobrien case 32: 121260484Sobrien u32 = (uint32_t*)(p + j * pixel_size); 121360484Sobrien mouse_buf32[i * 16 + j] = *u32; 121460484Sobrien if (mouse_or_mask[i] & (1 << (15 - j))) 121560484Sobrien writel(u32, vga_palette32[15]); 121660484Sobrien else if (mouse_and_mask[i] & (1 << (15 - j))) 121760484Sobrien writel(u32, 0); 121860484Sobrien break; 121960484Sobrien case 16: 122060484Sobrien u16 = (uint16_t*)(p + j * pixel_size); 122160484Sobrien mouse_buf16[i * 16 + j] = *u16; 122260484Sobrien if (mouse_or_mask[i] & (1 << (15 - j))) 122360484Sobrien writew(u16, vga_palette16[15]); 122460484Sobrien else if (mouse_and_mask[i] & (1 << (15 - j))) 122560484Sobrien writew(u16, 0); 122660484Sobrien break; 122760484Sobrien case 15: 122860484Sobrien u16 = (uint16_t*)(p + j * pixel_size); 122960484Sobrien mouse_buf16[i * 16 + j] = *u16; 123060484Sobrien if (mouse_or_mask[i] & (1 << (15 - j))) 123160484Sobrien writew(u16, vga_palette15[15]); 123260484Sobrien else if (mouse_and_mask[i] & (1 << (15 - j))) 123360484Sobrien writew(u16, 0); 123460484Sobrien break; 123560484Sobrien case 8: 123660484Sobrien u8 = (uint8_t*)(p + j * pixel_size); 123760484Sobrien mouse_buf8[i * 16 + j] = *u8; 123860484Sobrien if (mouse_or_mask[i] & (1 << (15 - j))) 123960484Sobrien writeb(u8, 15); 124060484Sobrien else if (mouse_and_mask[i] & (1 << (15 - j))) 124160484Sobrien writeb(u8, 0); 124260484Sobrien break; 124360484Sobrien } 124460484Sobrien } 124560484Sobrien 124660484Sobrien p += line_width; 124760484Sobrien } 124860484Sobrien 124960484Sobrien x_old = x; 125077298Sobrien y_old = y; 125160484Sobrien xend_old = xend; 125260484Sobrien yend_old = yend; 125377298Sobrien} 125460484Sobrien 125560484Sobrienstatic void 125677298Sobrienvga_pxlmouse_planar(scr_stat *scp, int x, int y, int on) 125760484Sobrien{ 125860484Sobrien if (on) 125960484Sobrien draw_pxlmouse_planar(scp, x, y); 126060484Sobrien else 126160484Sobrien remove_pxlmouse_planar(scp, x, y); 126260484Sobrien} 126360484Sobrien 126460484Sobrien#endif /* SC_NO_CUTPASTE */ 126560484Sobrien#endif /* SC_PIXEL_MODE */ 126660484Sobrien 126760484Sobrien#ifndef SC_NO_MODE_CHANGE 126860484Sobrien 126960484Sobrien/* graphics mode renderer */ 127060484Sobrien 127160484Sobrienstatic void 127260484Sobrienvga_grborder(scr_stat *scp, int color) 127360484Sobrien{ 127460484Sobrien vidd_set_border(scp->sc->adp, color); 127560484Sobrien} 127660484Sobrien 127760484Sobrien#endif 127860484Sobrien