diff options
Diffstat (limited to 'xserver/hw/kdrive/sis530')
-rw-r--r-- | xserver/hw/kdrive/sis530/sis.c | 921 | ||||
-rw-r--r-- | xserver/hw/kdrive/sis530/sis.h | 1215 | ||||
-rw-r--r-- | xserver/hw/kdrive/sis530/sisclock.c | 232 | ||||
-rw-r--r-- | xserver/hw/kdrive/sis530/siscmap.c | 64 | ||||
-rw-r--r-- | xserver/hw/kdrive/sis530/siscurs.c | 364 | ||||
-rw-r--r-- | xserver/hw/kdrive/sis530/sisdraw.c | 1649 | ||||
-rw-r--r-- | xserver/hw/kdrive/sis530/sisdraw.h | 180 | ||||
-rw-r--r-- | xserver/hw/kdrive/sis530/sisio.c | 30 | ||||
-rw-r--r-- | xserver/hw/kdrive/sis530/sisstub.c | 67 |
9 files changed, 4722 insertions, 0 deletions
diff --git a/xserver/hw/kdrive/sis530/sis.c b/xserver/hw/kdrive/sis530/sis.c new file mode 100644 index 000000000..e1deb3b28 --- /dev/null +++ b/xserver/hw/kdrive/sis530/sis.c @@ -0,0 +1,921 @@ +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "sis.h" + +#define MAX_FB_SIZE (4096 * 1024) + +#define MMIO_SIZE (64 * 1024) + +int sisMemoryTable[8] = { + 1, 2, 4, 0, 0, 2, 4, 8 +}; + +Bool +sisCardInit (KdCardInfo *card) +{ + SisCardInfo *sisc; + SisPtr sis; + int size; + CARD8 *registers; + CARD8 *temp_buffer; + CARD8 save_sr5; + + sisc = (SisCardInfo *) xalloc (sizeof (SisCardInfo)); + if (!sisc) + goto bail0; + + sisc->io_base = card->attr.io; + /* + * enable access to SiS ports (no MMIO available) + */ + iopl(3); + save_sr5 = GetSrtc(sisc,0x5); + if (save_sr5 != 0x21) + save_sr5 = 0x86; + PutSrtc(sisc,0x5,0x86); +#if 0 + { + int i; + + for (i = 0; i <= 0x3f; i++) + fprintf (stderr, "SR%02x = %02x\n", i, GetSrtc(sisc,i)); + } +#endif + sisc->memory = sisMemoryTable[GetSrtc(sisc,0xc)&0x7] * 1024 * 1024; + + PutSrtc(sisc,0x5,save_sr5); + + if (!sisc->memory) + { + ErrorF ("Can't detect SiS530 frame buffer\n"); + goto bail1; + } + + /* + * Map frame buffer and MMIO registers + */ + sisc->frameBuffer = KdMapDevice (card->attr.address[0], sisc->memory); + if (!sisc->frameBuffer) + goto bail1; + + sisc->registers = KdMapDevice (card->attr.address[1], MMIO_SIZE); + if (!sisc->registers) + goto bail2; + + /* + * Offset from base of MMIO to registers + */ + sisc->sis = (SisPtr) (sisc->registers + SIS_MMIO_OFFSET); + sisc->cpu_bitblt = (VOL32 *) sisc->registers; + + card->driver = sisc; + + return TRUE; +bail2: + KdUnmapDevice (sisc->frameBuffer, sisc->memory); +bail1: + xfree (sisc); +bail0: + return FALSE; +} + +Bool +sisModeSupported (KdScreenInfo *screen, const KdMonitorTiming *t) +{ + if (t->horizontal != 1600 && + t->horizontal != 1280 && + t->horizontal != 1152 && + t->horizontal != 1024 && + t->horizontal != 800 && + t->horizontal != 640) + return FALSE; + return TRUE; +} + +Bool +sisModeUsable (KdScreenInfo *screen) +{ + KdCardInfo *card = screen->card; + SisCardInfo *sisc = (SisCardInfo *) card->driver; + SisScreenInfo *siss; + int i; + KdMonitorTiming *t; + CARD32 memory; + int byte_width, pixel_width, screen_size; + + if (screen->fb[0].depth >= 24) + { + screen->fb[0].depth = 24; + screen->fb[0].bitsPerPixel = 24; + screen->dumb = TRUE; + } + else if (screen->fb[0].depth >= 16) + { + screen->fb[0].depth = 16; + screen->fb[0].bitsPerPixel = 16; + } + else if (screen->fb[0].depth >= 15) + { + screen->fb[0].depth = 15; + screen->fb[0].bitsPerPixel = 16; + } + else + { + screen->fb[0].depth = 8; + screen->fb[0].bitsPerPixel = 8; + } + byte_width = screen->width * (screen->fb[0].bitsPerPixel >> 3); + pixel_width = screen->width; + screen->fb[0].pixelStride = pixel_width; + screen->fb[0].byteStride = byte_width; + + screen_size = byte_width * screen->height; + + return screen_size <= sisc->memory; +} + +Bool +sisScreenInit (KdScreenInfo *screen) +{ + KdCardInfo *card = screen->card; + SisCardInfo *sisc = (SisCardInfo *) card->driver; + SisScreenInfo *siss; + int i; + const KdMonitorTiming *t; + CARD32 memory; + int byte_width, pixel_width, screen_size; + + siss = (SisScreenInfo *) xalloc (sizeof (SisScreenInfo)); + if (!siss) + return FALSE; + + memset (siss, '\0', sizeof (SisScreenInfo)); + + if (!screen->width || !screen->height) + { + screen->width = 800; + screen->height = 600; + screen->rate = 72; + } + if (!screen->fb[0].depth) + screen->fb[0].depth = 8; + + t = KdFindMode (screen, sisModeSupported); + + screen->rate = t->rate; + screen->width = t->horizontal; + screen->height = t->vertical; + + if (!KdTuneMode (screen, sisModeUsable, sisModeSupported)) + { + xfree (sisc); + return FALSE; + } + + memory = sisc->memory - screen_size; + + screen->fb[0].frameBuffer = sisc->frameBuffer; + + /* + * Cursor lives in the last 16k of memory + */ + if (memory >= 16384 && !screen->softCursor) + { + siss->cursor_base = sisc->frameBuffer + (sisc->memory - 16384); + siss->cursor_off = siss->cursor_base - sisc->frameBuffer; + memory -= 16384; + } + else + { + screen->softCursor = TRUE; + siss->cursor_base = 0; + siss->cursor_off = 0; + } + + if (memory > 8192) + { + siss->expand = screen->fb[0].frameBuffer + screen_size; + siss->expand_off = siss->expand - sisc->frameBuffer; + siss->expand_len = memory; + memory = 0; + } + else + { + siss->expand = 0; + siss->expand_len = 0; + } + + switch (screen->fb[0].depth) { + case 8: + screen->fb[0].visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)); + screen->fb[0].blueMask = 0x00; + screen->fb[0].greenMask = 0x00; + screen->fb[0].redMask = 0x00; + break; + case 15: + screen->fb[0].visuals = (1 << TrueColor); + screen->fb[0].blueMask = 0x001f; + screen->fb[0].greenMask = 0x03e0; + screen->fb[0].redMask = 0x7c00; + break; + case 16: + screen->fb[0].visuals = (1 << TrueColor); + screen->fb[0].blueMask = 0x001f; + screen->fb[0].greenMask = 0x07e0; + screen->fb[0].redMask = 0xf800; + break; + case 24: + screen->fb[0].visuals = (1 << TrueColor); + screen->fb[0].blueMask = 0x0000ff; + screen->fb[0].greenMask = 0x00ff00; + screen->fb[0].redMask = 0xff0000; + break; + } + + screen->driver = siss; + + return TRUE; +} + +static void +_sisGetCrtc (SisCardInfo *sisc, SisCrtc *crtc) +{ + crtc->misc_output = _sisInb(sisc->io_base+0x4c); + crtc->h_total_0_7 = GetCrtc (sisc, 0x00); + crtc->h_display_end_0_7 = GetCrtc (sisc, 0x01); + crtc->h_blank_start_0_7 = GetCrtc (sisc, 0x02); + crtc->_h_blank_end = GetCrtc (sisc, 0x03); + crtc->h_sync_start_0_7 = GetCrtc (sisc, 0x04); + crtc->_h_sync_end = GetCrtc (sisc, 0x05); + crtc->v_total_0_7 = GetCrtc (sisc, 0x06); + crtc->crtc_overflow = GetCrtc (sisc, 0x07); + crtc->preset_row_scan = GetCrtc (sisc, 0x08); + crtc->_max_scan_line = GetCrtc (sisc, 0x09); + crtc->cursor_start = GetCrtc (sisc, 0x0a); + crtc->cursor_end = GetCrtc (sisc, 0x0a); + crtc->start_address_8_15 = GetCrtc (sisc, 0x0c); + crtc->start_address_0_7 = GetCrtc (sisc, 0x0d); + crtc->text_cursor_15_8 = GetCrtc (sisc, 0x0e); + crtc->text_cursor_7_0 = GetCrtc (sisc, 0x0f); + crtc->v_retrace_start_0_7 = GetCrtc (sisc, 0x10); + crtc->_v_retrace_end = GetCrtc (sisc, 0x11); + crtc->v_display_end_0_7 = GetCrtc (sisc, 0x12); + crtc->screen_off_0_7 = GetCrtc (sisc, 0x13); + crtc->_underline_location = GetCrtc (sisc, 0x14); + crtc->v_blank_start_0_7 = GetCrtc (sisc, 0x15); + crtc->v_blank_end_0_7 = GetCrtc (sisc, 0x16); + crtc->crtc_mode = GetCrtc (sisc, 0x17); + + crtc->line_compare_0_7 = GetCrtc (sisc, 0x18); + + crtc->mode_control = GetArtc (sisc, 0x10); + crtc->screen_border_color = GetArtc (sisc, 0x11); + crtc->enable_color_plane = GetArtc (sisc, 0x12); + crtc->horizontal_pixel_pan = GetArtc (sisc, 0x13); + + crtc->mode_register = GetGrtc (sisc, 0x5); + crtc->misc_register = GetGrtc (sisc, 0x6); + crtc->color_dont_care = GetGrtc (sisc, 0x7); + + crtc->clock_mode = GetSrtc (sisc, 0x1); + crtc->color_plane_w_enable = GetSrtc (sisc, 0x2); + crtc->memory_mode = GetSrtc (sisc, 0x4); + + crtc->graphics_mode = GetSrtc (sisc, 0x6); + crtc->misc_control_0 = GetSrtc (sisc, 0x7); + crtc->crt_cpu_threshold_control_0 = GetSrtc (sisc, 0x8); + crtc->crt_cpu_threshold_control_1 = GetSrtc (sisc, 0x9); + crtc->extended_crt_overflow = GetSrtc (sisc, 0xa); + crtc->misc_control_1 = GetSrtc (sisc, 0xb); + crtc->misc_control_2 = GetSrtc (sisc, 0xc); + + crtc->ddc_and_power_control = GetSrtc (sisc, 0x11); + crtc->extended_horizontal_overflow = GetSrtc (sisc, 0x12); + crtc->extended_clock_generator = GetSrtc (sisc, 0x13); + crtc->cursor_0_red = GetSrtc (sisc, 0x14); + crtc->cursor_0_green = GetSrtc (sisc, 0x15); + crtc->cursor_0_blue = GetSrtc (sisc, 0x16); + crtc->cursor_1_red = GetSrtc (sisc, 0x17); + crtc->cursor_1_green = GetSrtc (sisc, 0x18); + crtc->cursor_1_blue = GetSrtc (sisc, 0x19); + crtc->cursor_h_start_0_7 = GetSrtc (sisc, 0x1a); + crtc->cursor_h_start_1 = GetSrtc (sisc, 0x1b); + crtc->cursor_h_preset_0_5 = GetSrtc (sisc, 0x1c); + crtc->cursor_v_start_0_7 = GetSrtc (sisc, 0x1d); + crtc->cursor_v_start_1 = GetSrtc (sisc, 0x1e); + crtc->cursor_v_preset_0_5 = GetSrtc (sisc, 0x1f); + crtc->linear_base_19_26 = GetSrtc (sisc, 0x20); + crtc->linear_base_1 = GetSrtc (sisc, 0x21); + + crtc->graphics_engine_0 = GetSrtc (sisc, 0x26); + crtc->graphics_engine_1 = GetSrtc (sisc, 0x27); + crtc->internal_mclk_0 = GetSrtc (sisc, 0x28); + crtc->internal_mclk_1 = GetSrtc (sisc, 0x29); + crtc->internal_vclk_0 = GetSrtc (sisc, 0x2A); + crtc->internal_vclk_1 = GetSrtc (sisc, 0x2B); + + crtc->misc_control_7 = GetSrtc (sisc, 0x38); + + crtc->misc_control_11 = GetSrtc (sisc, 0x3E); + crtc->misc_control_12 = GetSrtc (sisc, 0x3F); +} + +static void +_sisSetBlank (SisCardInfo *sisc, Bool blank) +{ + CARD8 clock; + + clock = GetSrtc (sisc, 0x01); + if (blank) + clock |= 0x20; + else + clock &= ~0x20; + PutSrtc (sisc, 0x01, clock); +} + +static void +_sisSetCrtc (SisCardInfo *sisc, SisCrtc *crtc) +{ + _sisSetBlank (sisc, TRUE); + PutCrtc (sisc, 0x00, crtc->h_total_0_7); + PutCrtc (sisc, 0x01, crtc->h_display_end_0_7); + PutCrtc (sisc, 0x02, crtc->h_blank_start_0_7); + PutCrtc (sisc, 0x03, crtc->_h_blank_end); + PutCrtc (sisc, 0x04, crtc->h_sync_start_0_7); + PutCrtc (sisc, 0x05, crtc->_h_sync_end); + PutCrtc (sisc, 0x06, crtc->v_total_0_7); + PutCrtc (sisc, 0x07, crtc->crtc_overflow); + PutCrtc (sisc, 0x08, crtc->preset_row_scan); + PutCrtc (sisc, 0x09, crtc->_max_scan_line); + PutCrtc (sisc, 0x0a, crtc->cursor_start); + PutCrtc (sisc, 0x0b, crtc->cursor_end); + PutCrtc (sisc, 0x0c, crtc->start_address_8_15); + PutCrtc (sisc, 0x0d, crtc->start_address_0_7); + PutCrtc (sisc, 0x0e, crtc->text_cursor_15_8); + PutCrtc (sisc, 0x0f, crtc->text_cursor_7_0); + PutCrtc (sisc, 0x10, crtc->v_retrace_start_0_7); + PutCrtc (sisc, 0x11, crtc->_v_retrace_end); + PutCrtc (sisc, 0x12, crtc->v_display_end_0_7); + PutCrtc (sisc, 0x13, crtc->screen_off_0_7); + PutCrtc (sisc, 0x14, crtc->_underline_location); + PutCrtc (sisc, 0x15, crtc->v_blank_start_0_7); + PutCrtc (sisc, 0x16, crtc->v_blank_end_0_7); + PutCrtc (sisc, 0x17, crtc->crtc_mode); + PutCrtc (sisc, 0x18, crtc->line_compare_0_7); + + PutArtc (sisc, 0x10, crtc->mode_control); + PutArtc (sisc, 0x11, crtc->screen_border_color); + PutArtc (sisc, 0x12, crtc->enable_color_plane); + PutArtc (sisc, 0x13, crtc->horizontal_pixel_pan); + + PutGrtc (sisc, 0x5, crtc->mode_register); + PutGrtc (sisc, 0x6, crtc->misc_register); + PutGrtc (sisc, 0x7, crtc->color_dont_care); + + PutSrtc (sisc, 0x1, crtc->clock_mode | 0x20); + PutSrtc (sisc, 0x2, crtc->color_plane_w_enable); + PutSrtc (sisc, 0x4, crtc->memory_mode); + + PutSrtc (sisc, 0x6, crtc->graphics_mode); + PutSrtc (sisc, 0x7, crtc->misc_control_0); + PutSrtc (sisc, 0x8, crtc->crt_cpu_threshold_control_0); + PutSrtc (sisc, 0x9, crtc->crt_cpu_threshold_control_1); + PutSrtc (sisc, 0xa, crtc->extended_crt_overflow); + PutSrtc (sisc, 0xb, crtc->misc_control_1); + PutSrtc (sisc, 0xc, crtc->misc_control_2); + + PutSrtc (sisc, 0x11, crtc->ddc_and_power_control); + PutSrtc (sisc, 0x12, crtc->extended_horizontal_overflow); + PutSrtc (sisc, 0x13, crtc->extended_clock_generator); + PutSrtc (sisc, 0x14, crtc->cursor_0_red); + PutSrtc (sisc, 0x15, crtc->cursor_0_green); + PutSrtc (sisc, 0x16, crtc->cursor_0_blue); + PutSrtc (sisc, 0x17, crtc->cursor_1_red); + PutSrtc (sisc, 0x18, crtc->cursor_1_green); + PutSrtc (sisc, 0x19, crtc->cursor_1_blue); + PutSrtc (sisc, 0x1a, crtc->cursor_h_start_0_7); + PutSrtc (sisc, 0x1b, crtc->cursor_h_start_1); + PutSrtc (sisc, 0x1c, crtc->cursor_h_preset_0_5); + PutSrtc (sisc, 0x1d, crtc->cursor_v_start_0_7); + PutSrtc (sisc, 0x1e, crtc->cursor_v_start_1); + PutSrtc (sisc, 0x1f, crtc->cursor_v_preset_0_5); + PutSrtc (sisc, 0x20, crtc->linear_base_19_26); + PutSrtc (sisc, 0x21, crtc->linear_base_1); + + PutSrtc (sisc, 0x26, crtc->graphics_engine_0); + PutSrtc (sisc, 0x27, crtc->graphics_engine_1); + PutSrtc (sisc, 0x28, crtc->internal_mclk_0); + PutSrtc (sisc, 0x29, crtc->internal_mclk_1); + PutSrtc (sisc, 0x2A, crtc->internal_vclk_0); + PutSrtc (sisc, 0x2B, crtc->internal_vclk_1); + + PutSrtc (sisc, 0x38, crtc->misc_control_7); + + PutSrtc (sisc, 0x3E, crtc->misc_control_11); + PutSrtc (sisc, 0x3F, crtc->misc_control_12); + +#if 0 + PutCrtc (sisc, 0x5b, 0x27); + PutCrtc (sisc, 0x5c, 0xe1); + PutCrtc (sisc, 0x5d, 0x00); + + PutSrtc (sisc, 0x5a, 0xe6); + PutSrtc (sisc, 0x5d, 0xa1); + PutSrtc (sisc, 0x9a, 0xe6); + PutSrtc (sisc, 0x9d, 0xa1); + PutSrtc (sisc, 0xda, 0xe6); + PutSrtc (sisc, 0xdd, 0x6c); +#endif + + _sisOutb(crtc->misc_output, sisc->io_base+0x42); + + outw (0x3c4, 0x0100); + outw (0x3c4, 0x0300); + + _sisSetBlank (sisc, FALSE); +} + +CARD8 +_sisReadIndexRegister (CARD32 base, CARD8 index) +{ + CARD8 ret; + + _sisOutb (index, base); + ret = _sisInb (base+1); + return ret; +} + +void +_sisWriteIndexRegister (CARD32 base, CARD8 index, CARD8 value) +{ + _sisOutb (index, base); + _sisOutb (value, base+1); +} + +CARD8 +_sisReadArtc (CARD32 base, CARD8 index) +{ + CARD8 ret; + + _sisInb (base+0x1a); + _sisOutb (index,base); + ret = _sisInb (base+1); + _sisInb (base+0x1a); + _sisOutb (0x20,base); + return ret; +} + +void +_sisWriteArtc (CARD32 base, CARD8 index, CARD8 value) +{ + _sisInb (base+0x1a); + _sisOutb (index|0x20,base); + _sisOutb (value,base); + _sisInb (base+0x1a); + _sisOutb (0x20,base); +} + +void +sisPreserve (KdCardInfo *card) +{ + SisCardInfo *sisc = card->driver; + CARD8 *r = sisc->registers; + int a, i, l; + CARD8 line[16]; + CARD8 prev[16]; + BOOL gotone; + + sisc->save.sr5 = GetSrtc(sisc,0x5); + if (sisc->save.sr5 != 0x21) + sisc->save.sr5 = 0x86; + /* unlock extension registers */ + PutSrtc(sisc,0x5,0x86); + /* unlock CRTC registers */ + PutCrtc(sisc,0x11,GetCrtc(sisc,0x11)&~0x80); + /* enable vga */ + _sisOutb(0x1,sisc->io_base+0x43); + + /* enable MMIO access to registers */ + sisc->save.srb = GetSrtc(sisc,0xb); + PutSrtc(sisc, 0xb, sisc->save.srb | 0x60); + _sisGetCrtc (sisc, &sisc->save.crtc); + memcpy (sisc->save.text_save, sisc->frameBuffer, SIS_TEXT_SAVE); +} + +Bool +sisEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + KdCardInfo *card = pScreenPriv->card; + SisCardInfo *sisc = card->driver; + SisScreenInfo *siss = screen->driver; + const KdMonitorTiming *t; + SisCrtc crtc; + unsigned long pixel; + + int hactive; + int hblank; + int hfp; + int hbp; + + int vactive; + int vblank; + int vfp; + int vbp; + + int h_total; + int h_display_end; + int h_blank_start; + int h_blank_end; + int h_sync_start; + int h_sync_end; + int h_screen_off; + + int h_adjust; + + int v_total; + int v_retrace_start; + int v_retrace_end; + int v_display_end; + int v_blank_start; + int v_blank_end; + + crtc = sisc->save.crtc; + + t = KdFindMode (screen, sisModeSupported); + + /* CR9 */ + crtc.max_scan_line = 0; + + /* CRA */ + crtc.cursor_start = 0; + + /* CRB */ + crtc.cursor_end = 0; + + /* CRE */ + crtc.text_cursor_15_8 = 0; + + /* CRF */ + crtc.text_cursor_7_0 = 0; + + /* CR11 */ + crtc.disable_v_retrace_int = 1; + + /* CR14 */ + crtc.underline_location = 0; + crtc.count_by_four = 0; + crtc.doubleword_mode = 1; + + /* 3CC/3C2 */ + crtc.io_address_select = 1; + crtc.display_ram_enable = 1; + crtc.clock_select = 3; + + /* SR1 */ + crtc.clock_mode = 0; + crtc.dot_clock_8_9 = 1; + + /* SR2 */ + crtc.color_plane_w_enable = 0xf; + + /* SR4 */ + crtc.memory_mode = 0; + crtc.chain_4_enable = 1; + crtc.odd_even_disable = 1; + crtc.extended_memory_sz = 1; + + /* SR6 */ + crtc.graphics_mode_linear = 1; + crtc.enhanced_graphics_mode = 1; + + /* SR9 */ + crtc.crt_cpu_threshold_control_1 = 0; + + /* SRB */ +#if 0 + crtc.cpu_bitblt_enable = 1; +#endif + crtc.memory_mapped_mode = 3; + + /* SRC */ + crtc.graphics_mode_32bit_enable = 1; + crtc.read_ahead_enable = 1; + + /* SR11 */ + crtc.acpi_enable = 0; + crtc.kbd_cursor_activate = 0; + crtc.video_memory_activate = 0; + crtc.vga_standby = 0; + crtc.vga_suspend = 0; + + crtc.cursor_0_red = 0x3f; + crtc.cursor_0_green = 0x3f; + crtc.cursor_0_blue = 0x3f; + + /* SR20 */ + crtc.linear_base_19_26 = (card->attr.address[0] & 0x07f80000) >> 19; + + /* SR21 */ + crtc.linear_base_27_31 = (card->attr.address[0] & 0xf8000000) >> 27; + crtc.linear_aperture = SIS_LINEAR_APERTURE_4M; + + /* SR27 */ + crtc.logical_screen_width = 3; + crtc.graphics_prog_enable = 1; + + /* SR38 */ + crtc.extended_clock_select = 0; + + /* AR10 */ + crtc.mode_control = 0; + crtc.graphics_mode_enable = 1; + /* AR11 */ + crtc.screen_border_color = 0; + /* AR12 */ + crtc.enable_color_plane = 0xf; + /* AR13 */ + crtc.horizontal_pixel_pan = 0; + + /* GR5 */ + crtc.mode_register = 0; + + /* GR6 */ + crtc.graphics_enable = 1; + crtc.chain_odd_even = 0; + crtc.memory_address_select = 1; + + /* GR7 */ + crtc.color_dont_care = 0xf; + if (siss->cursor_base) + { + crtc_set_cursor_start_addr (&crtc, siss->cursor_off); + crtc.graphics_mode_hw_cursor = 0; + } + + hactive = t->horizontal; + hblank = t->hblank; + hbp = t->hbp; + hfp = t->hfp; + + vactive = t->vertical; + vblank = t->vblank; + vbp = t->vbp; + vfp = t->vfp; + + pixel = (hactive + hblank) * (vactive + vblank) * t->rate; + + switch (screen->fb[0].bitsPerPixel) { + case 8: + hactive /= 8; + hblank /= 8; + hfp /= 8; + hbp /= 8; + + crtc.color_mode_256 = 1; + h_screen_off = hactive; + h_adjust = 1; + + break; + case 16: + hactive /= 8; + hblank /= 8; + hfp /= 8; + hbp /= 8; + + h_screen_off = hactive * 2; + h_adjust = 1; + + crtc.color_mode_256 = 0; + + if (screen->fb[0].depth == 15) + crtc.graphics_mode_32k = 1; + else + crtc.graphics_mode_64k = 1; + break; + case 24: + hactive /= 8; + hblank /= 8; + hfp /= 8; + hbp /= 8; + + h_screen_off = hactive * 3; + h_adjust = 1; + + crtc.color_mode_256 = 0; + + /* SR6 */ + crtc.graphics_mode_true = 1; + /* SR7 */ + crtc.direct_color_24bit = 0; + /* SR9 */ + crtc.true_color_32bpp = 0; + /* SRB */ + crtc.true_color_order = 1; + break; + case 32: + hactive /= 8; + hblank /= 8; + hfp /= 8; + hbp /= 8; + + h_screen_off = hactive * 4; + h_adjust = 1; + + crtc.color_mode_256 = 0; + + /* SR6 */ + crtc.graphics_mode_true = 1; + /* SR7 */ + crtc.direct_color_24bit = 0; + /* SR9 */ + crtc.true_color_32bpp = 1; + /* SRB */ + crtc.true_color_order = 1; + break; + } + + sisGetClock (pixel, &crtc); + + crtc.high_speed_dac_0 = crtc.high_speed_dac_1 = pixel > 135000000; + + sisEngThresh (&crtc, pixel, screen->fb[0].bitsPerPixel); + + /* + * Compute horizontal register values from timings + */ + h_total = hactive + hblank - 5; + h_display_end = hactive - 1; + h_blank_start = h_display_end; + h_blank_end = h_blank_start + hblank; + + h_sync_start = hactive + hfp + h_adjust; + h_sync_end = h_sync_start + hblank - hbp - hfp; + + crtc_set_h_total(&crtc, h_total); + crtc_set_h_display_end (&crtc, h_display_end); + crtc_set_h_blank_start (&crtc, h_blank_start); + crtc_set_h_blank_end (&crtc, h_blank_end); + crtc_set_h_sync_start (&crtc, h_sync_start); + crtc_set_h_sync_end (&crtc, h_sync_end); + crtc_set_screen_off (&crtc, h_screen_off); + + v_total = vactive + vblank - 2; + v_retrace_start = vactive + vfp - 1; + v_retrace_end = v_retrace_start + vblank - vbp - vfp; + v_display_end = vactive - 1; + v_blank_start = vactive - 1; + v_blank_end = v_blank_start + vblank /* - 1 */; + + crtc_set_v_total(&crtc, v_total); + crtc_set_v_retrace_start (&crtc, v_retrace_start); + crtc.v_retrace_end_0_3 = v_retrace_end; + crtc_set_v_display_end (&crtc, v_display_end); + crtc_set_v_blank_start (&crtc, v_blank_start); + crtc.v_blank_end_0_7 = v_blank_end; + +#if 0 + crtc.h_blank_start_0_7 = 0x6a; + crtc._h_blank_end = 0x9a; + crtc.h_sync_start_0_7 = 0x6b; + crtc._h_sync_end = 0x9a; + + crtc.v_retrace_start_0_7 = 0x7d; + crtc._v_retrace_end = 0x23; + crtc.v_blank_start_0_7 = 0x7d; + crtc.v_blank_end_0_7 = 0x84; + + crtc.crt_cpu_threshold_control_0 = 0xdf; /* SR8 */ + crtc.crt_cpu_threshold_control_1 = 0x00; /* SR9 */ + crtc.extended_clock_generator = 0x40; /* SR13 */ + + crtc.cursor_h_start_0_7 = 0x83; + crtc.cursor_v_start_0_7 = 0x6c; + + crtc.internal_vclk_0 = 0x68; + crtc.internal_vclk_1 = 0xc4; + crtc.misc_control_7 = 0x70; +#endif + + _sisSetCrtc (sisc, &crtc); + return TRUE; +} + +Bool +sisDPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + sisCardInfo(pScreenPriv); + union ddc_and_power_control_u _ddc_and_power_control_u; + + ddc_and_power_control = sisc->save.crtc.ddc_and_power_control; + + kbd_cursor_activate = 0; + video_memory_activate = 0; + vga_standby = 0; + vga_suspend = 0; + acpi_enable = 0; + switch (mode) { + case KD_DPMS_NORMAL: + break; + case KD_DPMS_STANDBY: + vga_standby = 1; + break; + case KD_DPMS_SUSPEND: + vga_suspend = 1; + break; + case KD_DPMS_POWERDOWN: + acpi_enable = 1; + break; + } + PutSrtc (sisc, 0x11, ddc_and_power_control); + return TRUE; +} + +void +sisDisable (ScreenPtr pScreen) +{ +} + +void +sisRestore (KdCardInfo *card) +{ + SisCardInfo *sisc = (SisCardInfo *) card->driver; + + memcpy (sisc->frameBuffer, sisc->save.text_save, SIS_TEXT_SAVE); + _sisSetCrtc (sisc, &sisc->save.crtc); + PutSrtc (sisc, 0xb, sisc->save.srb); + PutSrtc (sisc, 0x5, sisc->save.sr5); +} + +void +sisScreenFini (KdScreenInfo *screen) +{ + SisScreenInfo *siss = (SisScreenInfo *) screen->driver; + + xfree (siss); + screen->driver = 0; +} + +void +sisCardFini (KdCardInfo *card) +{ + SisCardInfo *sisc = (SisCardInfo *) card->driver; + + KdUnmapDevice (sisc->frameBuffer, sisc->memory); + KdUnmapDevice (sisc->registers, sizeof (SisRec)); +} + +KdCardFuncs sisFuncs = { + sisCardInit, + sisScreenInit, + 0, + sisPreserve, + sisEnable, + sisDPMS, + sisDisable, + sisRestore, + sisScreenFini, + sisCardFini, + sisCursorInit, + sisCursorEnable, + sisCursorDisable, + sisCursorFini, + 0, + sisDrawInit, + sisDrawEnable, + sisDrawSync, + sisDrawDisable, + sisDrawFini, + sisGetColors, + sisPutColors, +}; diff --git a/xserver/hw/kdrive/sis530/sis.h b/xserver/hw/kdrive/sis530/sis.h new file mode 100644 index 000000000..194c33c02 --- /dev/null +++ b/xserver/hw/kdrive/sis530/sis.h @@ -0,0 +1,1215 @@ +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, 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. + */ + +#ifndef _SIS_H_ +#define _SIS_H_ +#include "kdrive.h" +#include <stdio.h> +#include <unistd.h> +#include <sys/mman.h> +#include <asm/io.h> +#include <stdio.h> + +/* + * Linear Addressing 000 0000 - 0ff ffff (16m) + * Image data transfer 100 0000 - 100 7fff (32k) + * Empty 100 8000 - 100 81ff + * MMIO registers 100 8200 - 100 8480 + * + * We don't care about the image transfer or PCI regs, so + * this structure starts at the MMIO regs + */ + +typedef volatile CARD32 VOL32; +typedef volatile CARD16 VOL16; +typedef volatile CARD8 VOL8; + +#define SIS_MMIO_OFFSET 0x8200 + +typedef struct _sis530General { + VOL32 src_base; /* 8200 */ + VOL16 src_pitch; /* 8204 */ + VOL16 _pad0; /* 8206 */ + VOL16 src_y; /* 8208 */ + VOL16 src_x; /* 820a */ + VOL16 dst_y; /* 820c */ + VOL16 dst_x; /* 820e */ + VOL32 dst_base; /* 8210 */ + VOL16 dst_pitch; /* 8214 */ + VOL16 dst_height; /* 8216 */ + VOL16 rect_width; /* 8218 */ + VOL16 rect_height; /* 821a */ + VOL32 pattern_fg; /* 821c */ + VOL32 pattern_bg; /* 8220 */ + VOL32 src_fg; /* 8224 */ + VOL32 src_bg; /* 8228 */ + VOL8 mask[8]; /* 822c */ + VOL16 clip_left; /* 8234 */ + VOL16 clip_top; /* 8236 */ + VOL16 clip_right; /* 8238 */ + VOL16 clip_bottom; /* 823a */ + VOL32 command; /* 823c */ + VOL32 status; /* 8240 */ + VOL8 _pad1[0xbc]; /* 8244 */ + VOL8 pattern[256]; /* 8300 */ + /* 8400 */ +} SisGeneral; + +typedef struct _sis530Line { + VOL8 _pad0[8]; /* 8200 */ + VOL16 x0; /* 8208 */ + VOL16 y0; /* 820a */ + VOL16 x1; /* 820c */ + VOL16 y1; /* 820e */ + VOL32 dst_base; /* 8210 */ + VOL16 dst_pitch; /* 8214 */ + VOL16 dst_height; /* 8216 */ + VOL16 count; /* 8218 */ + VOL16 style_period; /* 821a */ + VOL32 fg; /* 821c */ + VOL32 bg; /* 8220 */ + VOL8 _pad1[8]; /* 8224 */ + VOL32 style0; /* 822c */ + VOL32 style1; /* 8228 */ + VOL16 clip_left; /* 8234 */ + VOL16 clip_top; /* 8236 */ + VOL16 clip_right; /* 8238 */ + VOL16 clip_bottom; /* 823a */ + VOL32 command; /* 823c */ + VOL32 status; /* 8240 */ + VOL8 _pad2[0xbc]; /* 8244 */ + struct { + VOL16 x; + VOL16 y; + } data[96]; /* 8300 */ + /* 8480 */ +} SisLine; + +typedef struct _sis530Transparent { + VOL32 src_base; /* 8200 */ + VOL16 src_pitch; /* 8204 */ + VOL16 _pad0; /* 8206 */ + VOL16 src_y; /* 8208 */ + VOL16 src_x; /* 820a */ + VOL16 dst_y; /* 820c */ + VOL16 dst_x; /* 820e */ + VOL32 dst_base; /* 8210 */ + VOL16 dst_pitch; /* 8214 */ + VOL16 dst_height; /* 8216 */ + VOL16 rect_width; /* 8218 */ + VOL16 rect_height; /* 821a */ + VOL32 dst_key_high; /* 821c */ + VOL32 dst_key_low; /* 8220 */ + VOL32 src_key_high; /* 8224 */ + VOL32 src_key_low; /* 8228 */ + VOL8 _pad1[8]; /* 822c */ + VOL16 clip_left; /* 8234 */ + VOL16 clip_top; /* 8236 */ + VOL16 clip_right; /* 8238 */ + VOL16 clip_bottom; /* 823a */ + VOL32 command; /* 823c */ + VOL32 status; /* 8240 */ + /* 8244 */ +} SisTransparent; + +typedef struct _sis530Multiple { + VOL8 _pad0[8]; /* 8200 */ + VOL16 count; /* 8208 */ + VOL16 y; /* 820a */ + VOL16 x0_start; /* 820c */ + VOL16 x0_end; /* 820e */ + VOL32 dst_base; /* 8210 */ + VOL16 dst_pitch; /* 8214 */ + VOL16 dst_height; /* 8216 */ + VOL8 _pad1[4]; /* 8218 */ + VOL32 fg; /* 821c */ + VOL32 bg; /* 8220 */ + VOL8 _pad2[8]; /* 8224 */ + VOL8 mask[8]; /* 822c */ + VOL16 clip_left; /* 8234 */ + VOL16 clip_top; /* 8236 */ + VOL16 clip_right; /* 8238 */ + VOL16 clip_bottom; /* 823a */ + VOL32 command; /* 823c */ + VOL32 status; /* 8240 */ + VOL16 x1_start; /* 8244 */ + VOL16 x1_end; /* 8246 */ + VOL8 _pad3[0xb8]; /* 8248 */ + VOL8 pattern[64]; /* 8300 */ + struct { + VOL16 x_start; + VOL16 y_end; + } data[80]; /* 8340 */ + /* 8480 */ +} SisMultiple; + +typedef struct _sis530Trapezoid { + VOL8 _pad0[8]; /* 8200 */ + VOL16 height; /* 8208 */ + VOL16 y; /* 820a */ + VOL16 left_x; /* 820c */ + VOL16 right_x; /* 820e */ + VOL32 dst_base; /* 8210 */ + VOL16 dst_pitch; /* 8214 */ + VOL16 dst_height; /* 8216 */ + VOL8 _pad1[4]; /* 8218 */ + VOL32 fg; /* 821c */ + VOL32 bg; /* 8220 */ + VOL8 _pad2[8]; /* 8224 */ + VOL8 mask[8]; /* 822c */ + VOL16 clip_left; /* 8234 */ + VOL16 clip_top; /* 8236 */ + VOL16 clip_right; /* 8238 */ + VOL16 clip_bottom; /* 823a */ + VOL32 command; /* 823c */ + VOL32 status; /* 8240 */ + VOL16 left_dx; /* 8244 */ + VOL16 left_dy; /* 8246 */ + VOL16 right_dx; /* 8248 */ + VOL16 right_dy; /* 824a */ + VOL32 left_error; /* 824c */ + VOL32 right_error; /* 8250 */ + /* 8254 */ +} SisTrapezoid; + +typedef struct _sisAccel { + VOL8 pad[0x80]; /* 8200 */ + VOL32 src_addr; /* 8280 */ + VOL32 dst_addr; /* 8284 */ + VOL32 pitch; /* 8288 */ + VOL32 dimension; /* 828c */ + VOL32 fg; /* 8290 */ + VOL32 bg; /* 8294 */ + + + VOL32 clip_ul; /* 82a0 */ + VOL32 clip_br; /* 82a4 */ + + VOL16 cmd; /* 82aa */ + + VOL8 pattern[256]; /* 82ac */ + +} SisAccel; + +typedef struct _sis530 { + union { + SisGeneral general; + SisLine line; + SisTransparent transparent; + SisMultiple multiple; + SisTrapezoid trapezoid; + SisAccel accel; + } u; +} SisRec, *SisPtr; + +typedef struct _sisCursor { + int width, height; + int xhot, yhot; + Bool has_cursor; + CursorPtr pCursor; +} SisCursor; + +#define SIS_CURSOR_WIDTH 64 +#define SIS_CURSOR_HEIGHT 64 + +typedef struct _sisClock { + CARD32 vclk_numerator; + BOOL vclk_divide_by_2; + CARD32 vclk_denominator; + CARD32 vclk_post_scale; + BOOL vclk_post_scale_2; + BOOL high_speed_dac; +} SisClockRec, *SisClockPtr; + +typedef struct _crtc { + + union { + struct { + CARD8 _io_address_select : 1; + CARD8 _display_ram_enable : 1; + CARD8 _clock_select : 2; + CARD8 : 1; + CARD8 _odd_even_page : 1; + CARD8 _h_sync_polarity : 1; + CARD8 _v_sync_polarity : 1; + } _misc_output_s; + CARD8 _misc_output; + } _misc_output_u; /* 3CC/3C2 */ + +#define misc_output _misc_output_u._misc_output +#define io_address_select _misc_output_u._misc_output_s._io_address_select +#define display_ram_enable _misc_output_u._misc_output_s._display_ram_enable +#define clock_select _misc_output_u._misc_output_s._clock_select +#define odd_even_page _misc_output_u._misc_output_s._odd_even_page +#define h_sync_polarity _misc_output_u._misc_output_s._h_sync_polarity +#define v_sync_polarity _misc_output_u._misc_output_s._v_sync_polarity + + CARD8 h_total_0_7; /* CR0 */ + CARD8 h_display_end_0_7; /* CR1 */ + CARD8 h_blank_start_0_7; /* CR2 */ + union { + struct { + CARD8 _h_blank_end_0_4 : 5; + CARD8 _display_skew : 2; + CARD8 : 1; + } _h_blank_end_s; + CARD8 __h_blank_end; /* CR3 */ + } _h_blank_end_u; +#define h_blank_end_0_4 _h_blank_end_u._h_blank_end_s._h_blank_end_0_4 +#define display_skew _h_blank_end_u._h_blank_end_s._display_skew +#define _h_blank_end _h_blank_end_u.__h_blank_end + + CARD8 h_sync_start_0_7; /* CR4 */ + + union { + struct { + CARD8 _h_sync_end_0_4 : 5; + CARD8 _horizontal_skew : 2; + CARD8 _h_blank_end_5 : 1; + } _h_sync_end_s; + CARD8 __h_sync_end; /* CR5 */ + } _h_sync_end_u; + +#define h_sync_end_0_4 _h_sync_end_u._h_sync_end_s._h_sync_end_0_4 +#define horizontal_skew _h_sync_end_u._h_sync_end_s._horizontal_skew +#define h_blank_end_5 _h_sync_end_u._h_sync_end_s._h_blank_end_5 +#define _h_sync_end _h_sync_end_u.__h_sync_end + + CARD8 v_total_0_7; /* CR6 */ + + union { + struct { + CARD8 _v_total_8 : 1; + CARD8 _v_display_end_8 : 1; + CARD8 _v_retrace_start_8 : 1; + CARD8 _v_blank_start_8 : 1; + CARD8 _line_compare_8 : 1; + CARD8 _v_total_9 : 1; + CARD8 _v_display_end_9 : 1; + CARD8 _v_retrace_start_9 : 1; + } _crtc_overflow_s; + CARD8 _crtc_overflow; /* CR7 */ + } _crtc_overflow_u; + +#define v_total_8 _crtc_overflow_u._crtc_overflow_s._v_total_8 +#define v_display_end_8 _crtc_overflow_u._crtc_overflow_s._v_display_end_8 +#define v_retrace_start_8 _crtc_overflow_u._crtc_overflow_s._v_retrace_start_8 +#define v_blank_start_8 _crtc_overflow_u._crtc_overflow_s._v_blank_start_8 +#define line_compare_8 _crtc_overflow_u._crtc_overflow_s._line_compare_8 +#define v_total_9 _crtc_overflow_u._crtc_overflow_s._v_total_9 +#define v_display_end_9 _crtc_overflow_u._crtc_overflow_s._v_display_end_9 +#define v_retrace_start_9 _crtc_overflow_u._crtc_overflow_s._v_retrace_start_9 +#define crtc_overflow _crtc_overflow_u._crtc_overflow + + CARD8 preset_row_scan; /* CR8 (unused) */ + + union { + struct { + CARD8 ___max_scan_line : 5; + CARD8 _v_blank_start_9 : 1; + CARD8 _line_compare_9 : 1; + CARD8 _double_scan : 1; + } _max_scan_line_s; + CARD8 __max_scan_line; /* CR9 */ + } _max_scan_line_u; + +#define max_scan_line _max_scan_line_u._max_scan_line_s.___max_scan_line +#define v_blank_start_9 _max_scan_line_u._max_scan_line_s._v_blank_start_9 +#define line_compare_9 _max_scan_line_u._max_scan_line_s._line_compare_9 +#define double_scan _max_scan_line_u._max_scan_line_s._double_scan +#define _max_scan_line _max_scan_line_u.__max_scan_line + + CARD8 cursor_start; /* CRA */ + CARD8 cursor_end; /* CRB */ + + CARD8 start_address_8_15; /* CRC */ + CARD8 start_address_0_7; /* CRD */ + + CARD8 text_cursor_15_8; /* CRE */ + CARD8 text_cursor_7_0; /* CRF */ + + CARD8 cursor_loc_high; + CARD8 cursor_loc_low; + + CARD8 v_retrace_start_0_7; /* CR10 */ + union { + struct { + CARD8 _v_retrace_end_0_3 : 4; + CARD8 _clear_v_retrace_int : 1; + CARD8 _disable_v_retrace_int : 1; + CARD8 _refresh_cycle_select : 1; + CARD8 _lock_crtc : 1; + } _v_retrace_end_s; + CARD8 __v_retrace_end; /* CR11 */ + } _v_retrace_end_u; + +#define v_retrace_end_0_3 _v_retrace_end_u._v_retrace_end_s._v_retrace_end_0_3 +#define clear_v_retrace_int _v_retrace_end_u._v_retrace_end_s._clear_v_retrace_int +#define disable_v_retrace_int _v_retrace_end_u._v_retrace_end_s._disable_v_retrace_int +#define refresh_cycle_select _v_retrace_end_u._v_retrace_end_s._refresh_cycle_select +#define lock_crtc _v_retrace_end_u._v_retrace_end_s._lock_crtc +#define _v_retrace_end _v_retrace_end_u.__v_retrace_end + + CARD8 v_display_end_0_7; /* CR12 */ + + CARD8 screen_off_0_7; /* CR13 */ + + union { + struct { + CARD8 ___underline_location : 5; + CARD8 _count_by_four : 1; + CARD8 _doubleword_mode : 1; + CARD8 : 1; + } _underline_location_s; + CARD8 __underline_location; /* CR14 */ + } _underline_location_u; + +#define underline_location _underline_location_u._underline_location_s.___underline_location +#define count_by_four _underline_location_u._underline_location_s._count_by_four +#define doubleword_mode _underline_location_u._underline_location_s._doubleword_mode +#define _underline_location _underline_location_u.__underline_location + + CARD8 v_blank_start_0_7; /* CR15 */ + CARD8 v_blank_end_0_7; /* CR16 */ + + union { + struct { + CARD8 _two_bk_cga : 1; + CARD8 _four_bk_cga : 1; + CARD8 _v_total_double : 1; + CARD8 _count_by_two : 1; + CARD8 : 1; + CARD8 _address_wrap : 1; + CARD8 _byte_mode : 1; + CARD8 _hardware_reset : 1; + } _crtc_mode_s; + CARD8 _crtc_mode; /* CR17 */ + } _crtc_mode_u; + +#define crtc_mode _crtc_mode_u._crtc_mode +#define two_bk_cga _crtc_mode_u._crtc_mode_s._two_bk_cga +#define four_bk_cga _crtc_mode_u._crtc_mode_s._four_bk_cga +#define v_total_double _crtc_mode_u._crtc_mode_s._v_total_double +#define count_by_two _crtc_mode_u._crtc_mode_s._count_by_two +#define address_wrap _crtc_mode_u._crtc_mode_s._address_wrap +#define byte_mode _crtc_mode_u._crtc_mode_s._byte_mode +#define hardware_reset _crtc_mode_u._crtc_mode_s._hardware_reset + + CARD8 line_compare_0_7; /* CR18 (unused) */ + + union { + struct { + CARD8 _graphics_mode_enable : 1; + CARD8 _attribute_byte_mda : 1; + CARD8 _line_graphics_enable : 1; + CARD8 _background_blink : 1; + CARD8 : 1; + CARD8 _pel_panning_compat : 1; + CARD8 _pixel_clock_double : 1; + CARD8 p4_p5_source_select : 1; + } _mode_control_s; + CARD8 _mode_control; + } _mode_control_u; /* AR10 */ + +#define mode_control _mode_control_u._mode_control +#define graphics_mode_enable _mode_control_u._mode_control_s._graphics_mode_enable +#define pixel_clock_double _mode_control_u._mode_control_s._pixel_clock_double + + CARD8 screen_border_color; /* AR11 */ + CARD8 enable_color_plane; /* AR12 */ + CARD8 horizontal_pixel_pan; /* AR13 */ + + union { + struct { + CARD8 _write_mode : 2; + CARD8 : 1; + CARD8 _read_mode : 1; + CARD8 _odd_even_addressing : 1; + CARD8 _shift_register_mode : 1; + CARD8 _color_mode_256 : 1; + CARD8 : 1; + } _mode_register_s; + CARD8 _mode_register; + } _mode_register_u; /* GR5 */ + +#define mode_register _mode_register_u._mode_register +#define color_mode_256 _mode_register_u._mode_register_s._color_mode_256 +#define odd_even_addressing _mode_register_u._mode_register_s._odd_even_addressing + + union { + struct { + CARD8 _graphics_enable : 1; + CARD8 _chain_odd_even : 1; + CARD8 _memory_address_select : 2; + CARD8 : 4; + } _misc_register_s; + CARD8 _misc_register; + } _misc_register_u; /* GR6 */ + +#define misc_register _misc_register_u._misc_register +#define graphics_enable _misc_register_u._misc_register_s._graphics_enable +#define chain_odd_even _misc_register_u._misc_register_s._chain_odd_even +#define memory_address_select _misc_register_u._misc_register_s._memory_address_select + + CARD8 color_dont_care; /* GR7 */ + + union { + struct { + CARD8 _dot_clock_8_9 : 1; + CARD8 : 1; + CARD8 _shifter_load_16 : 1; + CARD8 _dot_clock_divide_2 : 1; + CARD8 _shifter_load_32 : 1; + CARD8 _display_off : 1; + CARD8 : 2; + } _clock_mode_s; + CARD8 _clock_mode; + } _clock_mode_u; /* SR1 */ + +#define clock_mode _clock_mode_u._clock_mode +#define dot_clock_8_9 _clock_mode_u._clock_mode_s._dot_clock_8_9 +#define shifter_load_16 _clock_mode_u._clock_mode_s._shifter_load_16 +#define dot_clock_divide_2 _clock_mode_u._clock_mode_s._dot_clock_divide_2 +#define shifter_load_32 _clock_mode_u._clock_mode_s._shifter_load_32 +#define display_off _clock_mode_u._clock_mode_s._display_off + + CARD8 color_plane_w_enable; /* SR2 */ + + union { + struct { + CARD8 : 1; + CARD8 _extended_memory_size : 1; + CARD8 _odd_even_disable : 1; + CARD8 _chain_4_enable : 1; + CARD8 : 4; + } _memory_mode_s; + CARD8 _memory_mode; + } _memory_mode_u; /* SR4 */ + +#define memory_mode _memory_mode_u._memory_mode +#define extended_memory_sz _memory_mode_u._memory_mode_s._extended_memory_size +#define odd_even_disable _memory_mode_u._memory_mode_s._odd_even_disable +#define chain_4_enable _memory_mode_u._memory_mode_s._chain_4_enable + + union { + struct { + CARD8 _enhanced_text_mode : 1; + CARD8 _enhanced_graphics_mode : 1; + CARD8 _graphics_mode_32k : 1; + CARD8 _graphics_mode_64k : 1; + CARD8 _graphics_mode_true : 1; + CARD8 _graphics_mode_interlaced: 1; + CARD8 _graphics_mode_hw_cursor: 1; + CARD8 _graphics_mode_linear : 1; + } _graphics_mode_s; + CARD8 _graphics_mode; + } _graphics_mode_u; /* SR6 */ + +#define graphics_mode _graphics_mode_u._graphics_mode +#define enhanced_text_mode _graphics_mode_u._graphics_mode_s._enhanced_text_mode +#define enhanced_graphics_mode _graphics_mode_u._graphics_mode_s._enhanced_graphics_mode +#define graphics_mode_32k _graphics_mode_u._graphics_mode_s._graphics_mode_32k +#define graphics_mode_64k _graphics_mode_u._graphics_mode_s._graphics_mode_64k +#define graphics_mode_true _graphics_mode_u._graphics_mode_s._graphics_mode_true +#define graphics_mode_interlaced _graphics_mode_u._graphics_mode_s._graphics_mode_interlaced +#define graphics_mode_hw_cursor _graphics_mode_u._graphics_mode_s._graphics_mode_hw_cursor +#define graphics_mode_linear _graphics_mode_u._graphics_mode_s._graphics_mode_linear + + union { + struct { + CARD8 _external_dac_reference : 1; + CARD8 _high_speed_dac_0 : 1; + CARD8 _direct_color_24bit : 1; + CARD8 _multi_line_prefetch : 1; + CARD8 _extended_video_div_2 : 1; + CARD8 _ramdac_power_save : 1; + CARD8 : 1; + CARD8 _merge_video_fifo : 1; + } _misc_control_0_s; + CARD8 _misc_control_0; + } _misc_control_0_u; /* SR7 */ + +#define misc_control_0 _misc_control_0_u._misc_control_0 +#define external_dac_reference _misc_control_0_u._misc_control_0_s._external_dac_reference +#define high_speed_dac_0 _misc_control_0_u._misc_control_0_s._high_speed_dac_0 +#define direct_color_24bit _misc_control_0_u._misc_control_0_s._direct_color_24bit +#define multi_line_prefetch _misc_control_0_u._misc_control_0_s._multi_line_prefetch +#define extended_video_div_2 _misc_control_0_u._misc_control_0_s._extended_video_div_2 +#define ramdac_power_save _misc_control_0_u._misc_control_0_s._ramdac_power_save +#define merge_video_fifo _misc_control_0_u._misc_control_0_s._merge_video_fifo + + union { + struct { + CARD8 _crt_engine_threshold_high_0_3 : 4; + CARD8 _crt_cpu_threshold_low_0_3 : 4; + } _crt_cpu_threshold_control_0_s; + CARD8 _crt_cpu_threshold_control_0; + } _crt_cpu_threshold_control_0_u; /* SR8 */ + +#define crt_cpu_threshold_control_0 _crt_cpu_threshold_control_0_u._crt_cpu_threshold_control_0 +#define crt_engine_threshold_high_0_3 _crt_cpu_threshold_control_0_u._crt_cpu_threshold_control_0_s._crt_engine_threshold_high_0_3 +#define crt_cpu_threshold_low_0_3 _crt_cpu_threshold_control_0_u._crt_cpu_threshold_control_0_s._crt_cpu_threshold_low_0_3 + + union { + struct { + CARD8 _crt_cpu_threshold_high_0_3 : 4; + CARD8 _ascii_attribute_threshold_0_2 : 3; + CARD8 _true_color_32bpp : 1; + } _crt_cpu_threshold_control_1_s; + CARD8 _crt_cpu_threshold_control_1; + } _crt_cpu_threshold_control_1_u; /* SR9 */ + +#define crt_cpu_threshold_control_1 _crt_cpu_threshold_control_1_u._crt_cpu_threshold_control_1 +#define crt_cpu_threshold_high_0_3 _crt_cpu_threshold_control_1_u._crt_cpu_threshold_control_1_s._crt_cpu_threshold_high_0_3 +#define ascii_attribute_threshold_0_2 _crt_cpu_threshold_control_1_u._crt_cpu_threshold_control_1_s._ascii_attribute_threshold_0_2 +#define true_color_32bpp _crt_cpu_threshold_control_1_u._crt_cpu_threshold_control_1_s._true_color_32bpp + + union { + struct { + CARD8 _v_total_10 : 1; + CARD8 _v_display_end_10 : 1; + CARD8 _v_blank_start_10 : 1; + CARD8 _v_retrace_start_10 : 1; + CARD8 _screen_off_8_11 : 4; + } _extended_crt_overflow_s; + CARD8 _extended_crt_overflow; + } _extended_crt_overflow_u; /* SRA */ + +#define extended_crt_overflow _extended_crt_overflow_u._extended_crt_overflow +#define v_total_10 _extended_crt_overflow_u._extended_crt_overflow_s._v_total_10 +#define v_display_end_10 _extended_crt_overflow_u._extended_crt_overflow_s._v_display_end_10 +#define v_blank_start_10 _extended_crt_overflow_u._extended_crt_overflow_s._v_blank_start_10 +#define v_retrace_start_10 _extended_crt_overflow_u._extended_crt_overflow_s._v_retrace_start_10 +#define screen_off_8_11 _extended_crt_overflow_u._extended_crt_overflow_s._screen_off_8_11 + + union { + struct { + CARD8 _cpu_bitblt_enable : 1; /* enable CPU bitblt */ + CARD8 _packed_16_color_enable : 1; /* 2 pixels per byte? */ + CARD8 _io_gating : 1; /* when write buffer not empty */ + CARD8 _dual_segment_enable : 1; /* ? */ + CARD8 _true_color_modulation : 1; /* ? */ + CARD8 _memory_mapped_mode : 2; /* mmio enable */ + CARD8 _true_color_order : 1; /* 0: RGB 1: BGR */ + } _misc_control_1_s; + CARD8 _misc_control_1; /* SRB */ + } _misc_control_1_u; + +#define misc_control_1 _misc_control_1_u._misc_control_1 +#define cpu_bitblt_enable _misc_control_1_u._misc_control_1_s._cpu_bitblt_enable +#define memory_mapped_mode _misc_control_1_u._misc_control_1_s._memory_mapped_mode +#define true_color_modulation _misc_control_1_u._misc_control_1_s._true_color_modulation +#define true_color_order _misc_control_1_u._misc_control_1_s._true_color_order + + union { + struct { + CARD8 _sync_reset_enable : 1; + CARD8 _memory_configuration : 3; +#define SIS_MEMORY_CONFIG_1M_1BANK 0 +#define SIS_MEMORY_CONFIG_2M_2BANK 1 +#define SIS_MEMORY_CONFIG_4M_2BANK 2 +#define SIS_MEMORY_CONFIG_2M_1BANK 5 +#define SIS_MEMORY_CONFIG_4M_1BANK 6 +#define SIS_MEMORY_CONFIG_8M_2BANK 7 + CARD8 _test_mode_enable : 1; + CARD8 _read_ahead_enable : 1; + CARD8 _text_mode_16bit_enable : 1; + CARD8 _graphics_mode_32bit_enable : 1; + } _misc_control_2_s; + CARD8 _misc_control_2; + } _misc_control_2_u; /* SRC */ + +#define misc_control_2 _misc_control_2_u._misc_control_2 +#define sync_reset_enable _misc_control_2_u._misc_control_2_s._sync_reset_enable +#define memory_configuration _misc_control_2_u._misc_control_2_s._memory_configuration +#define test_mode_enable _misc_control_2_u._misc_control_2_s._test_mode_enable +#define read_ahead_enable _misc_control_2_u._misc_control_2_s._read_ahead_enable +#define text_mode_16bit_enable _misc_control_2_u._misc_control_2_s._text_mode_16bit_enable +#define graphics_mode_32bit_enable _misc_control_2_u._misc_control_2_s._graphics_mode_32bit_enable + + union ddc_and_power_control_u { + struct { + CARD8 _ddc_clk_programming : 1; + CARD8 _ddc_data_programming : 1; + CARD8 : 1; + CARD8 _acpi_enable : 1; + CARD8 _kbd_cursor_activate : 1; + CARD8 _video_memory_activate : 1; + CARD8 _vga_standby : 1; + CARD8 _vga_suspend : 1; + } _ddc_and_power_control_s; + CARD8 _ddc_and_power_control; + } _ddc_and_power_control_u; /* SR11 */ + +#define ddc_and_power_control _ddc_and_power_control_u._ddc_and_power_control +#define ddc_clk_programming _ddc_and_power_control_u._ddc_and_power_control_s._ddc_clk_programming +#define ddc_data_programming _ddc_and_power_control_u._ddc_and_power_control_s._ddc_data_programming +#define acpi_enable _ddc_and_power_control_u._ddc_and_power_control_s._acpi_enable +#define kbd_cursor_activate _ddc_and_power_control_u._ddc_and_power_control_s._kbd_cursor_activate +#define video_memory_activate _ddc_and_power_control_u._ddc_and_power_control_s._video_memory_activate +#define vga_standby _ddc_and_power_control_u._ddc_and_power_control_s._vga_standby +#define vga_suspend _ddc_and_power_control_u._ddc_and_power_control_s._vga_suspend + + union { + struct { + CARD8 _h_total_8 : 1; + CARD8 _h_display_end_8 : 1; + CARD8 _h_blank_start_8 : 1; + CARD8 _h_sync_start_8 : 1; + CARD8 _h_blank_end_6 : 1; + CARD8 _h_retrace_skew : 3; + } _extended_horizontal_overflow_s; + CARD8 _extended_horizontal_overflow; + } _extended_horizontal_overflow_u; /* SR12 */ +#define extended_horizontal_overflow _extended_horizontal_overflow_u._extended_horizontal_overflow +#define h_total_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_total_8 +#define h_display_end_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_display_end_8 +#define h_blank_start_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_blank_start_8 +#define h_sync_start_8 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_sync_start_8 +#define h_blank_end_6 _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_blank_end_6 +#define h_retrace_skew _extended_horizontal_overflow_u._extended_horizontal_overflow_s._h_retrace_skew + + union { + struct { + CARD8 : 6; + CARD8 _vclk_post_scale_2 : 1; + CARD8 _mclk_post_scale_2 : 1; + } _extended_clock_generator_s; + CARD8 _extended_clock_generator; + } _extended_clock_generator_u; /* SR13 */ + +#define extended_clock_generator _extended_clock_generator_u._extended_clock_generator +#define vclk_post_scale_2 _extended_clock_generator_u._extended_clock_generator_s._vclk_post_scale_2 +#define mclk_post_scale_2 _extended_clock_generator_u._extended_clock_generator_s._mclk_post_scale_2 + + CARD8 cursor_0_red; /* SR14 */ + CARD8 cursor_0_green; /* SR15 */ + CARD8 cursor_0_blue; /* SR16 */ + + CARD8 cursor_1_red; /* SR17 */ + CARD8 cursor_1_green; /* SR18 */ + CARD8 cursor_1_blue; /* SR19 */ + + CARD8 cursor_h_start_0_7; /* SR1A */ + union { + struct { + CARD8 _cursor_h_start_8_11 : 4; + CARD8 : 3; + CARD8 _cursor_mmio_enable : 1; + } _cusor_h_start_1_s; + CARD8 _cursor_h_start_1; + } _cursor_h_start_1_u; /* SR1B */ + +#define cursor_h_start_1 _cursor_h_start_1_u._cursor_h_start_1 +#define cursor_h_start_8_11 _cursor_h_start_1_u._cursor_h_start_1_s._cursor_h_start_8_11 + + CARD8 cursor_h_preset_0_5; /* SR1C */ + + CARD8 cursor_v_start_0_7; /* SR1D */ + + union { + struct { + CARD8 _cursor_v_start_8_10 : 3; + CARD8 _cursor_side_pattern : 1; + CARD8 _cursor_pattern : 4; + } _cusor_v_start_1_s; + CARD8 _cursor_v_start_1; + } _cursor_v_start_1_u; /* SR1E */ + +#define cursor_v_start_1 _cursor_v_start_1_u._cursor_v_start_1 + + CARD8 cursor_v_preset_0_5; /* SR1F */ + + CARD8 linear_base_19_26; /* SR20 */ + + union { + struct { + CARD8 _linear_base_27_31 : 5; + CARD8 _linear_aperture : 3; +#define SIS_LINEAR_APERTURE_512K 0 +#define SIS_LINEAR_APERTURE_1M 1 +#define SIS_LINEAR_APERTURE_2M 2 +#define SIS_LINEAR_APERTURE_4M 3 +#define SIS_LINEAR_APERTURE_8M 4 + } _linear_base_1_s; + CARD8 _linear_base_1; + } _linear_base_1_u; /* SR21 */ + +#define linear_base_1 _linear_base_1_u._linear_base_1 +#define linear_base_27_31 _linear_base_1_u._linear_base_1_s._linear_base_27_31 +#define linear_aperture _linear_base_1_u._linear_base_1_s._linear_aperture + + union { + struct { + CARD8 _screen_start_addr_20 : 1; + CARD8 : 3; + CARD8 _continuous_mem_access : 1; + CARD8 : 1; + CARD8 _power_down_dac : 1; + CARD8 : 1; + } _graphics_engine_0_s; + CARD8 _graphics_engine_0; + } _graphics_engine_0_u; /* SR26 */ + +#define graphics_engine_0 _graphics_engine_0_u._graphics_engine_0 + + + union { + struct { + CARD8 _screen_start_addr_16_19: 4; + CARD8 _logical_screen_width : 2; +#define SIS_LOG_SCREEN_WIDTH_1024 0 +#define SIS_LOG_SCREEN_WIDTH_2048 1 +#define SIS_LOG_SCREEN_WIDTH_4096 2 + CARD8 _graphics_prog_enable : 1; + CARD8 _turbo_queue_enable : 1; + } _graphics_engine_1_s; + CARD8 _graphics_engine_1; + } _graphics_engine_1_u; /* SR27 */ + +#define graphics_engine_1 _graphics_engine_1_u._graphics_engine_1 +#define screen_start_addr_16_19 _graphics_engine_1_u._graphics_engine_1_s._screen_start_addr_16_19 +#define logical_screen_width _graphics_engine_1_u._graphics_engine_1_s._logical_screen_width +#define graphics_prog_enable _graphics_engine_1_u._graphics_engine_1_s._graphics_prog_enable +#define turbo_queue_enable _graphics_engine_1_u._graphics_engine_1_s._turbo_queue_enable + + + union { + struct { + CARD8 _mclk_numerator : 7; + CARD8 _mclk_divide_by_2 : 1; + } _internal_mclk_0_s; + CARD8 _internal_mclk_0; + } _internal_mclk_0_u; /* SR28 */ + +#define internal_mclk_0 _internal_mclk_0_u._internal_mclk_0 +#define mclk_numerator _internal_mclk_0_u._internal_mclk_0_s._mclk_numerator +#define mclk_divide_by_2 _internal_mclk_0_u._internal_mclk_0_s._mclk_divide_by_2 + + union { + struct { + CARD8 _mclk_denominator : 5; + CARD8 _mclk_post_scale : 2; +#define SIS_MCLK_POST_SCALE_1 0 +#define SIS_MCLK_POST_SCALE_2 1 +#define SIS_MCLK_POST_SCALE_3 2 +#define SIS_MCLK_POST_SCALE_4 3 + CARD8 _mclk_vco_gain : 1; + } _internal_mclk_1_s; + CARD8 _internal_mclk_1; + } _internal_mclk_1_u; /* SR29 */ + +#define internal_mclk_1 _internal_mclk_1_u._internal_mclk_1 +#define mclk_denominator _internal_mclk_1_u._internal_mclk_1_s._mclk_denominator +#define mclk_post_scale _internal_mclk_1_u._internal_mclk_1_s._mclk_post_scale +#define mclk_vco_gain _internal_mclk_1_u._internal_mclk_1_s._mclk_vco_gain + + union { + struct { + CARD8 _vclk_numerator : 7; + CARD8 _vclk_divide_by_2 : 1; + } _internal_vclk_0_s; + CARD8 _internal_vclk_0; + } _internal_vclk_0_u; /* SR2A */ + +#define internal_vclk_0 _internal_vclk_0_u._internal_vclk_0 +#define vclk_numerator _internal_vclk_0_u._internal_vclk_0_s._vclk_numerator +#define vclk_divide_by_2 _internal_vclk_0_u._internal_vclk_0_s._vclk_divide_by_2 + + union { + struct { + CARD8 _vclk_denominator : 5; + CARD8 _vclk_post_scale : 2; +#define SIS_VCLK_POST_SCALE_1 0 +#define SIS_VCLK_POST_SCALE_2 1 +#define SIS_VCLK_POST_SCALE_3 2 +#define SIS_VCLK_POST_SCALE_4 3 + CARD8 _vclk_vco_gain : 1; + } _internal_vclk_1_s; + CARD8 _internal_vclk_1; + } _internal_vclk_1_u; /* SR2B */ + +#define internal_vclk_1 _internal_vclk_1_u._internal_vclk_1 +#define vclk_denominator _internal_vclk_1_u._internal_vclk_1_s._vclk_denominator +#define vclk_post_scale _internal_vclk_1_u._internal_vclk_1_s._vclk_post_scale +#define vclk_vco_gain _internal_vclk_1_u._internal_vclk_1_s._vclk_vco_gain + + union { + struct { + CARD8 _extended_clock_select : 2; +#define SIS_CLOCK_SELECT_INTERNAL 0 +#define SIS_CLOCK_SELECT_25MHZ 1 +#define SIS_CLOCK_SELECT_28MHZ 2 + CARD8 _disable_line_compare : 1; + CARD8 _disable_pci_read_t_o : 1; + CARD8 _cursor_start_addr_18_21: 4; + } _misc_control_7_s; + CARD8 _misc_control_7; + } _misc_control_7_u; /* SR38 */ + +#define misc_control_7 _misc_control_7_u._misc_control_7 +#define extended_clock_select _misc_control_7_u._misc_control_7_s._extended_clock_select +#define disable_line_compare _misc_control_7_u._misc_control_7_s._disable_line_compare +#define disable_pci_read_t_o _misc_control_7_u._misc_control_7_s._disable_pci_read_t_o +#define cursor_start_addr_18_21 _misc_control_7_u._misc_control_7_s._cursor_start_addr_18_21 + + union { + struct { + CARD8 _high_speed_dclk : 1; + CARD8 _sgram_block_write : 1; + CARD8 _cursor_start_addr_22 : 1; + CARD8 _dram_texture_read : 1; + CARD8 _sgram_16mb : 1; + CARD8 _agp_signal_delay : 2; + CARD8 _dclk_off : 1; + } _misc_control_11_s; + CARD8 _misc_control_11; + } _misc_control_11_u; /* SR3E */ + +#define misc_control_11 _misc_control_11_u._misc_control_11 +#define high_speed_dclk _misc_control_11_u._misc_control_11_s._high_speed_dclk +#define sgram_block_write _misc_control_11_u._misc_control_11_s.__sgram_block_write +#define cursor_start_addr_22 _misc_control_11_u._misc_control_11_s._cursor_start_addr_22 +#define dram_texture_read _misc_control_11_u._misc_control_11_s._dram_texture_read +#define sgram_16mb _misc_control_11_u._misc_control_11_s._sgram_16mb +#define agp_signal_delay _misc_control_11_u._misc_control_11_s._agp_signal_delay +#define dclk_off _misc_control_11_u._misc_control_11_s._dclk_off + + union { + struct { + CARD8 : 1; + CARD8 _flat_panel_low_enable : 1; + CARD8 _crt_cpu_threshold_low_4: 1; + CARD8 _crt_engine_threshold_high_4: 1; + CARD8 _crt_cpu_threshold_high_4 : 1; + CARD8 _crt_threshold_full_control : 2; +#define SIS_CRT_32_STAGE_THRESHOLD 0 +#define SIS_CRT_64_STAGE_THRESHOLD 1 +#define SIS_CRT_63_STAGE_THRESHOLD 2 +#define SIS_CRT_256_STAGE_THRESHOLD 3 + CARD8 _high_speed_dac_1 : 1; + } _misc_control_12_s; + CARD8 _misc_control_12; + } _misc_control_12_u; /* SR3F */ +#define misc_control_12 _misc_control_12_u._misc_control_12 +#define flat_panel_low_enable _misc_control_12_u._misc_control_12_s._flat_panel_low_enable +#define crt_cpu_threshold_low_4 _misc_control_12_u._misc_control_12_s._crt_cpu_threshold_low_4 +#define crt_engine_threshold_high_4 _misc_control_12_u._misc_control_12_s._crt_engine_threshold_high_4 +#define crt_cpu_threshold_high_4 _misc_control_12_u._misc_control_12_s._crt_cpu_threshold_high_4 +#define crt_threshold_full_control _misc_control_12_u._misc_control_12_s._crt_threshold_full_control +#define high_speed_dac_1 _misc_control_12_u._misc_control_12_s._high_speed_dac_1 + + /* computed values */ + CARD16 ge_screen_pitch; + CARD8 bits_per_pixel; + CARD8 depth; + CARD8 double_pixel_mode; + CARD16 pixel_width; +} SisCrtc; + +#define crtc_v_total(crtc) ((crtc)->v_total_0_7 | \ + ((crtc)->v_total_8 << 8) | \ + ((crtc)->v_total_9 << 9) | \ + ((crtc)->v_total_10 << 10)) + +#define crtc_set_v_total(crtc,v) { \ + ((crtc))->v_total_0_7 = (v); \ + ((crtc))->v_total_8 = (v) >> 8; \ + ((crtc))->v_total_9 = (v) >> 9; \ + ((crtc))->v_total_10 = (v) >> 10; \ +} + +#define crtc_v_display_end(crtc) ((crtc)->v_display_end_0_7 | \ + ((crtc)->v_display_end_8 << 8) | \ + ((crtc)->v_display_end_9 << 9) | \ + ((crtc)->v_display_end_10 << 10)) + +#define crtc_set_v_display_end(crtc,v) {\ + ((crtc))->v_display_end_0_7 = (v); \ + ((crtc))->v_display_end_8 = (v) >> 8; \ + ((crtc))->v_display_end_9 = (v) >> 9; \ + ((crtc))->v_display_end_10 = (v) >> 10; \ +} + +#define crtc_v_retrace_start(crtc) ((crtc)->v_retrace_start_0_7 | \ + ((crtc)->v_retrace_start_8 << 8) | \ + ((crtc)->v_retrace_start_9 << 9) | \ + ((crtc)->v_retrace_start_10 << 10)) + +#define crtc_set_v_retrace_start(crtc,v) {\ + ((crtc))->v_retrace_start_0_7 = (v); \ + ((crtc))->v_retrace_start_8 = (v) >> 8; \ + ((crtc))->v_retrace_start_9 = (v) >> 9; \ + ((crtc))->v_retrace_start_10 = (v) >> 10; \ +} + +#define crtc_v_blank_start(crtc) ((crtc)->v_blank_start_0_7 | \ + ((crtc)->v_blank_start_8 << 8) | \ + ((crtc)->v_blank_start_9 << 9) | \ + ((crtc)->v_blank_start_10 << 10)) + +#define crtc_set_v_blank_start(crtc,v) {\ + ((crtc))->v_blank_start_0_7 = (v); \ + ((crtc))->v_blank_start_8 = (v) >> 8; \ + ((crtc))->v_blank_start_9 = (v) >> 9; \ + ((crtc))->v_blank_start_10 = (v) >> 10; \ +} + +#define crtc_h_total(crtc) ((crtc)->h_total_0_7 | \ + ((crtc)->h_total_8 << 8)) + +#define crtc_set_h_total(crtc,v) {\ + ((crtc))->h_total_0_7 = (v); \ + ((crtc))->h_total_8 = (v) >> 8; \ +} + +#define crtc_h_display_end(crtc) ((crtc)->h_display_end_0_7 | \ + ((crtc)->h_display_end_8 << 8)) + +#define crtc_set_h_display_end(crtc,v) {\ + ((crtc))->h_display_end_0_7 = (v); \ + ((crtc))->h_display_end_8 = (v) >> 8; \ +} + +#define crtc_h_blank_start(crtc) ((crtc)->h_blank_start_0_7 | \ + ((crtc)->h_blank_start_8 << 8)) + +#define crtc_set_h_blank_start(crtc,v) {\ + ((crtc))->h_blank_start_0_7 = (v); \ + ((crtc))->h_blank_start_8 = (v) >> 8; \ +} + +#define crtc_h_blank_end(crtc) ((crtc)->h_blank_end_0_4 | \ + ((crtc)->h_blank_end_5 << 5)) + +#define crtc_set_h_blank_end(crtc,v) {\ + ((crtc))->h_blank_end_0_4 = (v); \ + ((crtc))->h_blank_end_5 = (v) >> 5; \ +} + +#define crtc_h_sync_start(crtc) ((crtc)->h_sync_start_0_7 | \ + ((crtc)->h_sync_start_8 << 8)) + +#define crtc_set_h_sync_start(crtc,v) {\ + ((crtc))->h_sync_start_0_7 = (v); \ + ((crtc))->h_sync_start_8 = (v) >> 8; \ +} + +#define crtc_h_sync_end(crtc) ((crtc)->h_sync_end_0_4) + +#define crtc_set_h_sync_end(crtc,v) {\ + ((crtc))->h_sync_end_0_4 = (v); \ +} + +#define crtc_screen_off(crtc) ((crtc)->screen_off_0_7 | \ + ((crtc)->screen_off_8_11 << 8)) + +#define crtc_set_screen_off(crtc,v) {\ + ((crtc))->screen_off_0_7 = (v); \ + ((crtc))->screen_off_8_11 = (v) >> 8; \ +} + +#define crtc_ge_screen_width(crtc) ((crtc)->ge_screen_width_0_1 | \ + ((crtc)->ge_screen_width_2 << 2)) + +#define crtc_set_ge_screen_width(crtc,v) { \ + (crtc)->ge_screen_width_0_1 = (v); \ + (crtc)->ge_screen_width_2 = (v) >> 2; \ +} + +#define crtc_h_start_fifo_fetch(crtc) ((crtc)->h_start_fifo_fetch_0_7 | \ + ((crtc)->h_start_fifo_fetch_8 << 8)) + +#define crtc_set_h_start_fifo_fetch(crtc,v) {\ + (crtc)->h_start_fifo_fetch_0_7 = (v); \ + (crtc)->h_start_fifo_fetch_8 = (v) >> 8; \ +} + +#define crtc_start_address(crtc) ((crtc)->start_address_0_7 | \ + ((crtc)->start_address_8_15 << 8) | \ + ((crtc)->start_address_16_19 << 16)) + +#define crtc_set_start_address(crtc,v) {\ + (crtc)->start_address_0_7 = (v); \ + (crtc)->start_address_8_15 = (v) >> 8; \ + (crtc)->start_address_16_19 = (v) >> 16; \ +} + +#define crtc_line_compare(crtc) ((crtc)->line_compare_0_7 | \ + ((crtc)->line_compare_8 << 8) | \ + ((crtc)->line_compare_9 << 9) | \ + ((crtc)->line_compare_10 << 10)) + +#define crtc_set_line_compare(crtc,v) { \ + ((crtc))->line_compare_0_7 = (v); \ + ((crtc))->line_compare_8 = (v) >> 8; \ + ((crtc))->line_compare_9 = (v) >> 9; \ + ((crtc))->line_compare_10 = (v) >> 10; \ +} + +#define crtc_set_cursor_start_addr(crtc,v) { \ + (crtc)->cursor_start_addr_18_21 = (v) >> 18; \ + (crtc)->cursor_start_addr_22 = (v) >> 22; \ +} + +#define _sisOutb(v,r) outb(v,r) +#define _sisInb(r) inb(r) + +#define SIS_DAC_INDEX_READ 0x47 +#define SIS_DAC_INDEX_WRITE 0x48 +#define SIS_DAC_DATA 0x49 + +#define GetCrtc(sisc,i) _sisReadIndexRegister ((sisc)->io_base+0x54,i) +#define PutCrtc(sisc,i,v) _sisWriteIndexRegister ((sisc)->io_base+0x54,i,v) + +#define GetSrtc(sisc,i) _sisReadIndexRegister ((sisc)->io_base+0x44,i) +#define PutSrtc(sisc,i,v) _sisWriteIndexRegister ((sisc)->io_base+0x44,i,v) + +#define GetArtc(sisc,i) _sisReadArtc ((sisc)->io_base+0x40,i) +#define PutArtc(sisc,i,v) _sisWriteArtc ((sisc)->io_base+0x40,i,v) + +#define GetGrtc(sisc,i) _sisReadIndexRegister ((sisc)->io_base+0x4e,i) +#define PutGrtc(sisc,i,v) _sisWriteIndexRegister ((sisc)->io_base+0x4e,i,v) + +#define _sisWaitVRetrace(sisc) + +#define LockSis(sisc) +#define UnlockSis(sisc) + +typedef struct _sisTiming { + /* label */ + int horizontal; + int vertical; + int rate; + /* horizontal timing */ + int hfp; /* front porch */ + int hbp; /* back porch */ + int hblank; /* blanking */ + /* vertical timing */ + int vfp; /* front porch */ + int vbp; /* back porch */ + int vblank; /* blanking */ +} SisTiming; + +#define SIS_TEXT_SAVE (64*1024) + +typedef struct _sisSave { + CARD8 srb; + CARD8 sr5; + SisCrtc crtc; + CARD8 text_save[SIS_TEXT_SAVE]; +} SisSave; + +typedef struct _sisCardInfo { + SisPtr sis; + int memory; + CARD8 *frameBuffer; + CARD8 *registers; + VOL32 *cpu_bitblt; + CARD32 io_base; + SisSave save; +} SisCardInfo; + +typedef struct _sisScreenInfo { + CARD8 *cursor_base; + CARD32 cursor_off; + CARD8 *expand; + CARD32 expand_off; + int expand_len; + SisCursor cursor; +} SisScreenInfo; + +#define getSisCardInfo(kd) ((SisCardInfo *) ((kd)->card->driver)) +#define sisCardInfo(kd) SisCardInfo *sisc = getSisCardInfo(kd) + +#define getSisScreenInfo(kd) ((SisScreenInfo *) ((kd)->screen->driver)) +#define sisScreenInfo(kd) SisScreenInfo *siss = getSisScreenInfo(kd) + +Bool sisCardInit (KdCardInfo *); +Bool sisScreenInit (KdScreenInfo *); +Bool sisEnable (ScreenPtr pScreen); +void sisDisable (ScreenPtr pScreen); +void sisFini (ScreenPtr pScreen); + +Bool sisCursorInit (ScreenPtr pScreen); +void sisCursorEnable (ScreenPtr pScreen); +void sisCursorDisable (ScreenPtr pScreen); +void sisCursorFini (ScreenPtr pScreen); +void sisRecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdefs); + +Bool sisDrawInit (ScreenPtr pScreen); +void sisDrawEnable (ScreenPtr pScreen); +void sisDrawSync (ScreenPtr pScreen); +void sisDrawDisable (ScreenPtr pScreen); +void sisDrawFini (ScreenPtr pScreen); + +void sisGetColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs); +void sisPutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs); + +void SISInitCard (KdCardAttr *attr); + +CARD8 _sisReadIndexRegister (CARD32 base, CARD8 index); +void _sisWriteIndexRegister (CARD32 base, CARD8 index, CARD8 value); +CARD8 _sisReadArtc (CARD32 base, CARD8 index); +void _sisWriteArtc (CARD32 base, CARD8 index, CARD8 value); + +extern KdCardFuncs sisFuncs; + +/* + * sisclock.c + */ +void +sisGetClock (unsigned long clock, SisCrtc *crtc); + +void +sisEngThresh (SisCrtc *crtc, unsigned long vclk, int bpp); + +/* + * siscurs.c + */ + +Bool +sisCursorInit (ScreenPtr pScreen); + +void +sisCursorEnable (ScreenPtr pScreen); + +void +sisCursorDisable (ScreenPtr pScreen); + +void +sisCursorFini (ScreenPtr pScreen); + +/* sisdraw.c */ +Bool +sisDrawInit (ScreenPtr pScreen); + +void +sisDrawEnable (ScreenPtr pScreen); + +void +sisDrawDisable (ScreenPtr pScreen); + +void +sisDrawFini (ScreenPtr pScreen); + +#endif /* _SIS_H_ */ diff --git a/xserver/hw/kdrive/sis530/sisclock.c b/xserver/hw/kdrive/sis530/sisclock.c new file mode 100644 index 000000000..f73cdac9d --- /dev/null +++ b/xserver/hw/kdrive/sis530/sisclock.c @@ -0,0 +1,232 @@ +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "sis.h" +#include <stdio.h> + +#define FREF 14318180 +#define MIN_VCO FREF +#define MAX_VCO 230000000 +#define MAX_PSN 0 /* no pre scaler for this chip */ +#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */ +#define max_VLD 1 + +/* + * Compute clock values given target frequency + */ +void +sisGetClock (unsigned long clock, SisCrtc *crtc) +{ + unsigned char reg7, reg13, reg2a, reg2b; + int M, N, P, VLD; + + int bestM, bestN, bestP, bestPSN, bestVLD; + double bestError, abest = 42.0, bestFout; + + double Fvco, Fout; + double error, aerror; + + double target = (double) clock; + + int M_min = 2; + int M_max = 128; + + int low_N = 2; + int high_N = 32; + int PSN = 1; + + /* + * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler) + * + * M = Numerator [1:128] + * N = DeNumerator [1:32] + * VLD = Divider (Vco Loop Divider) : divide by 1, 2 + * P = Post Scaler : divide by 1, 2, 3, 4 + * PSN = Pre Scaler (Reference Divisor Select) + * + * result in vclk[] + */ + + P = 1; + if (target < MAX_VCO / 2) + P = 2; + if (target < MAX_VCO / 3) + P = 3; + if (target < MAX_VCO / 4) + P = 4; + if (target < MAX_VCO / 6) + P = 6; + if (target < MAX_VCO / 8) + P = 8; + + Fvco = P * target; + + for (N = low_N; N <= high_N; N++) + { + double M_desired = Fvco / FREF * N; + + if (M_desired > M_max * max_VLD) + continue; + + if ( M_desired > M_max ) + { + M = (int)(M_desired / 2 + 0.5); + VLD = 2; + } + else + { + M = (int)(M_desired + 0.5); + VLD = 1; + } + + Fout = (double)FREF * (M * VLD)/(N * P); + error = (target - Fout) / target; + aerror = (error < 0) ? -error : error; + if (aerror < abest) + { + abest = aerror; + bestError = error; + bestM = M; + bestN = N; + bestP = P; + bestPSN = PSN; + bestVLD = VLD; + bestFout = Fout; + } + } + + crtc->vclk_numerator = bestM - 1; + crtc->vclk_divide_by_2 = bestVLD == 2; + + crtc->vclk_denominator = bestN - 1; + switch (bestP) { + case 1: + crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_1; + crtc->vclk_post_scale_2 = 0; + break; + case 2: + crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_2; + crtc->vclk_post_scale_2 = 0; + break; + case 3: + crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_3; + crtc->vclk_post_scale_2 = 0; + break; + case 4: + crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_4; + crtc->vclk_post_scale_2 = 0; + break; + case 6: + crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_3; + crtc->vclk_post_scale_2 = 1; + break; + case 8: + crtc->vclk_post_scale = SIS_VCLK_POST_SCALE_4; + crtc->vclk_post_scale_2 = 1; + break; + } + + crtc->vclk_vco_gain = 1; + + /* + * Don't know how to set mclk for local frame buffer; for + * shared frame buffer, mclk is hardwired to bus speed (100MHz)? + */ +} + +sisCalcMclk (SisCrtc *crtc) +{ + int mclk, Numer, DeNumer; + double Divider, Scalar; + + Numer = crtc->mclk_numerator; + DeNumer = crtc->mclk_denominator; + Divider = crtc->mclk_divide_by_2 ? 2.0 : 1.0; + Scalar = 1.0; + if (crtc->mclk_post_scale_2) + { + switch (crtc->mclk_post_scale) { + case 2: + Scalar = 6.0; + break; + case 3: + Scalar = 8.0; + break; + } + } + else + { + switch (crtc->mclk_post_scale) { + case 0: + Scalar = 1.0; + break; + case 1: + Scalar = 2.0; + break; + case 2: + Scalar = 3.0; + break; + case 3: + Scalar = 4.0; + break; + } + } + + mclk = (int)(FREF*((double)(Numer+1)/(double)(DeNumer+1))*(Divider/Scalar)); + + return(mclk); +} + +#define UMA_FACTOR 60 +#define LFB_FACTOR 30 // Only if local frame buffer +#define SIS_SAYS_SO 0x1F // But how is the performance?? +#define CRT_ENG_THRESH 0x0F // But how is the performance?? +#define BUS_WIDTH 64 +#define DFP_BUS_WIDTH 32 // rumour has it for digital flat panel ?? +#define MEGAHZ (1<<20) + +void +sisEngThresh (SisCrtc *crtc, unsigned long vclk, int bpp) +{ + int threshlow, mclk; + + mclk = sisCalcMclk(crtc) / 1000000; + vclk = vclk / 1000000; + threshlow = ((((UMA_FACTOR*vclk*bpp)/ + (mclk*BUS_WIDTH))+1)/2)+4; + + crtc->crt_cpu_threshold_low_0_3 = threshlow; + crtc->crt_cpu_threshold_low_4 = threshlow >> 4; + + crtc->crt_cpu_threshold_high_0_3 = (SIS_SAYS_SO & 0xf); + crtc->crt_cpu_threshold_high_4 = 0; + + crtc->crt_engine_threshold_high_0_3 = CRT_ENG_THRESH; + crtc->crt_engine_threshold_high_4 = 1; + + crtc->ascii_attribute_threshold_0_2 = (SIS_SAYS_SO >> 4); + + crtc->crt_threshold_full_control = SIS_CRT_64_STAGE_THRESHOLD; +} diff --git a/xserver/hw/kdrive/sis530/siscmap.c b/xserver/hw/kdrive/sis530/siscmap.c new file mode 100644 index 000000000..2a28420c8 --- /dev/null +++ b/xserver/hw/kdrive/sis530/siscmap.c @@ -0,0 +1,64 @@ +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "sis.h" + +void +sisGetColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + sisCardInfo(pScreenPriv); + + LockSis (sisc); + while (ndef--) + { + _sisOutb (pdefs->pixel, sisc->io_base+SIS_DAC_INDEX_READ); + pdefs->red = _sisInb (sisc->io_base+SIS_DAC_DATA) << 10; + pdefs->green = _sisInb (sisc->io_base+SIS_DAC_DATA) << 10; + pdefs->blue = _sisInb (sisc->io_base+SIS_DAC_DATA) << 10; + pdefs++; + } + UnlockSis (sisc); +} + +void +sisPutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + sisCardInfo(pScreenPriv); + + LockSis(sisc); + _sisWaitVRetrace (sisc); + while (ndef--) + { + _sisOutb (pdefs->pixel, sisc->io_base+SIS_DAC_INDEX_WRITE); + _sisOutb (pdefs->red >> 10, sisc->io_base+SIS_DAC_DATA); + _sisOutb (pdefs->green >> 10, sisc->io_base+SIS_DAC_DATA); + _sisOutb (pdefs->blue >> 10, sisc->io_base+SIS_DAC_DATA); + pdefs++; + } + UnlockSis(sisc); +} + diff --git a/xserver/hw/kdrive/sis530/siscurs.c b/xserver/hw/kdrive/sis530/siscurs.c new file mode 100644 index 000000000..dad44471c --- /dev/null +++ b/xserver/hw/kdrive/sis530/siscurs.c @@ -0,0 +1,364 @@ +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "sis.h" +#include "cursorstr.h" + +#define SetupCursor(s) KdScreenPriv(s); \ + sisCardInfo(pScreenPriv); \ + sisScreenInfo(pScreenPriv); \ + SisPtr sis = sisc->sis; \ + SisCursor *pCurPriv = &siss->cursor + +static void +_sisMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CARD8 xlow, xhigh, ylow, yhigh; + CARD8 xoff, yoff; + + x -= pCurPriv->xhot; + xoff = 0; + if (x < 0) + { + xoff = -x; + x = 0; + } + y -= pCurPriv->yhot; + yoff = 0; + if (y < 0) + { + yoff = -y; + y = 0; + } + xlow = (CARD8) x; + xhigh = (CARD8) (x >> 8); + ylow = (CARD8) y; + yhigh = (CARD8) (y >> 8); + + PutSrtc (sisc, 0x5, 0x86); + PutSrtc (sisc, 0x1c, xoff & 0x3f); + PutSrtc (sisc, 0x1f, yoff & 0x3f); + + PutSrtc (sisc, 0x1a, xlow); + PutSrtc (sisc, 0x1b, xhigh & 0xf); + + PutSrtc (sisc, 0x1d, ylow); + PutSrtc (sisc, 0x1e, yhigh & 0x7); +} + +static void +sisMoveCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor (pScreen); + + if (!pCurPriv->has_cursor) + return; + + if (!pScreenPriv->enabled) + return; + + LockSis(sisc); + _sisMoveCursor (pScreen, x, y); + UnlockSis(sisc); +} + +static void +_sisSetCursorColors (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + /* set foreground */ + PutSrtc (sisc, 0x17, pCursor->foreRed >> 10); + PutSrtc (sisc, 0x18, pCursor->foreGreen >> 10); + PutSrtc (sisc, 0x19, pCursor->foreBlue >> 10); + + /* set background */ + PutSrtc (sisc, 0x14, pCursor->backRed >> 10); + PutSrtc (sisc, 0x15, pCursor->backGreen >> 10); + PutSrtc (sisc, 0x16, pCursor->backBlue >> 10); +} + +static void +sisLoadCursor (ScreenPtr pScreen, int x, int y) +{ + SetupCursor(pScreen); + CursorPtr pCursor = pCurPriv->pCursor; + CursorBitsPtr bits = pCursor->bits; + int w, h; + unsigned short *ram, r; + unsigned char *msk, *mskLine, *src, *srcLine; + unsigned short m, s; + + int i, j; + int cursor_address; + int src_stride, src_width; + + CARD8 sr6; + + /* + * Lock Sis so the cursor doesn't move while we're setting it + */ + LockSis(sisc); + + pCurPriv->pCursor = pCursor; + pCurPriv->xhot = pCursor->bits->xhot; + pCurPriv->yhot = pCursor->bits->yhot; + + /* + * Stick new image into cursor memory + */ + ram = (unsigned short *) siss->cursor_base; + mskLine = (unsigned char *) bits->mask; + srcLine = (unsigned char *) bits->source; + + h = bits->height; + if (h > SIS_CURSOR_HEIGHT) + h = SIS_CURSOR_HEIGHT; + + src_stride = BitmapBytePad(bits->width); /* bytes per line */ + src_width = (bits->width + 7) >> 3; + + for (i = 0; i < SIS_CURSOR_HEIGHT; i++) { + msk = mskLine; + src = srcLine; + mskLine += src_stride; + srcLine += src_stride; + for (j = 0; j < SIS_CURSOR_WIDTH / 8; j++) { + + unsigned short m, s; + + if (i < h && j < src_width) + { + m = *msk++; + s = *src++ & m; + m = ~m; + /* mask off right side */ + if (j == src_width - 1 && (bits->width & 7)) + { + m |= 0xff << (bits->width & 7); + } + } + else + { + m = 0xff; + s = 0x00; + } + + /* + * The SIS530 HW cursor format is: source(AND) bit, + * then a mask(XOR) bit, etc. + * byte swapping in sis530 is: + * abcd ==> cdab + */ + +#define bit(a,n) (((a) >> (n)) & 0x1) + + r = ((bit(m, 0) << 7) | (bit(s, 0) << 6) | + (bit(m, 1) << 5) | (bit(s, 1) << 4) | + (bit(m, 2) << 3) | (bit(s, 2) << 2) | + (bit(m, 3) << 1) | (bit(s, 3) << 0) | + (bit(m, 4) << 15) | (bit(s, 4) << 14) | + (bit(m, 5) << 13) | (bit(s, 5) << 12) | + (bit(m, 6) << 11) | (bit(s, 6) << 10) | + (bit(m, 7) << 9) | (bit(s, 7) << 8)); + + *ram++ = r; + } + } + + /* Set new color */ + _sisSetCursorColors (pScreen); + + /* Move to new position */ + _sisMoveCursor (pScreen, x, y); + + /* Enable cursor */ + sr6 = GetSrtc (sisc, 0x6); + sr6 |= 0x40; + PutSrtc (sisc, 0x6, sr6); + + UnlockSis(sisc); +} + +static void +sisUnloadCursor (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + CARD8 sr6; + + LockSis (sisc); + + /* Disable cursor */ + sr6 = GetSrtc (sisc, 0x6); + sr6 &= ~0x40; + PutSrtc (sisc, 0x6, sr6); + PutSrtc (sisc, 0x1b, 0x00); + + UnlockSis (sisc); +} + +static Bool +sisRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupCursor(pScreen); + + if (!pScreenPriv->enabled) + return TRUE; + + /* miRecolorCursor does this */ + if (pCurPriv->pCursor == pCursor) + { + if (pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + sisLoadCursor (pScreen, x, y); + } + } + return TRUE; +} + +static Bool +sisUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +static void +sisSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + SetupCursor(pScreen); + + pCurPriv->pCursor = pCursor; + + if (!pScreenPriv->enabled) + return; + + if (pCursor) + sisLoadCursor (pScreen, x, y); + else + sisUnloadCursor (pScreen); +} + +miPointerSpriteFuncRec sisPointerSpriteFuncs = { + sisRealizeCursor, + sisUnrealizeCursor, + sisSetCursor, + sisMoveCursor, +}; + +static void +sisQueryBestSize (int class, + unsigned short *pwidth, unsigned short *pheight, + ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + switch (class) + { + case CursorShape: + if (*pwidth > pCurPriv->width) + *pwidth = pCurPriv->width; + if (*pheight > pCurPriv->height) + *pheight = pCurPriv->height; + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + default: + fbQueryBestSize (class, pwidth, pheight, pScreen); + break; + } +} + +Bool +sisCursorInit (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!siss->cursor_base) + { + pCurPriv->has_cursor = FALSE; + return FALSE; + } + + pCurPriv->width = SIS_CURSOR_WIDTH; + pCurPriv->height= SIS_CURSOR_HEIGHT; + pScreen->QueryBestSize = sisQueryBestSize; + miPointerInitialize (pScreen, + &sisPointerSpriteFuncs, + &kdPointerScreenFuncs, + FALSE); + pCurPriv->has_cursor = TRUE; + pCurPriv->pCursor = NULL; + return TRUE; +} + +void +sisCursorEnable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + int x, y; + + miPointerPosition (&x, &y); + sisLoadCursor (pScreen, x, y); + } + else + sisUnloadCursor (pScreen); + } +} + +void +sisCursorDisable (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + if (!pScreenPriv->enabled) + return; + + if (pCurPriv->has_cursor) + { + if (pCurPriv->pCursor) + { + sisUnloadCursor (pScreen); + } + } +} + +void +sisCursorFini (ScreenPtr pScreen) +{ + SetupCursor (pScreen); + + pCurPriv->pCursor = NULL; +} diff --git a/xserver/hw/kdrive/sis530/sisdraw.c b/xserver/hw/kdrive/sis530/sisdraw.c new file mode 100644 index 000000000..595544348 --- /dev/null +++ b/xserver/hw/kdrive/sis530/sisdraw.c @@ -0,0 +1,1649 @@ +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "sis.h" +#include "sisdraw.h" + +#include "Xmd.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "mistruct.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "fb.h" +#include "migc.h" +#include "miline.h" + +CARD8 sisPatRop[16] = { + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0xa0, /* src AND dst */ + /* GXandReverse */ 0x50, /* src AND NOT dst */ + /* GXcopy */ 0xf0, /* src */ + /* GXandInverted*/ 0x0a, /* NOT src AND dst */ + /* GXnoop */ 0xaa, /* dst */ + /* GXxor */ 0x5a, /* src XOR dst */ + /* GXor */ 0xfa, /* src OR dst */ + /* GXnor */ 0x05, /* NOT src AND NOT dst */ + /* GXequiv */ 0xa5, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xf5, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x0f, /* NOT src */ + /* GXorInverted */ 0xaf, /* NOT src OR dst */ + /* GXnand */ 0x5f, /* NOT src OR NOT dst */ + /* GXset */ 0xff, /* 1 */ +}; + +CARD8 sisBltRop[16] = { + /* GXclear */ 0x00, /* 0 */ + /* GXand */ 0x88, /* src AND dst */ + /* GXandReverse */ 0x44, /* src AND NOT dst */ + /* GXcopy */ 0xcc, /* src */ + /* GXandInverted*/ 0x22, /* NOT src AND dst */ + /* GXnoop */ 0xaa, /* dst */ + /* GXxor */ 0x66, /* src XOR dst */ + /* GXor */ 0xee, /* src OR dst */ + /* GXnor */ 0x11, /* NOT src AND NOT dst */ + /* GXequiv */ 0x99, /* NOT src XOR dst */ + /* GXinvert */ 0x55, /* NOT dst */ + /* GXorReverse */ 0xdd, /* src OR NOT dst */ + /* GXcopyInverted*/ 0x33, /* NOT src */ + /* GXorInverted */ 0xbb, /* NOT src OR dst */ + /* GXnand */ 0x77, /* NOT src OR NOT dst */ + /* GXset */ 0xff, /* 1 */ +}; + +/* Align blts to this boundary or risk trashing an in-progress expand */ +#define SIS_MIN_PATTERN 8 + +/* Do plane bits in this increment to balance CPU and graphics engine */ +#define SIS_PATTERN_INC 1024 + +typedef struct _SisExpand { + SisCardInfo *sisc; + SisScreenInfo *siss; + CARD32 off; + int last; +} SisExpand; + +static void +sisExpandInit (ScreenPtr pScreen, + SisExpand *e) +{ + KdScreenPriv(pScreen); + sisCardInfo(pScreenPriv); + sisScreenInfo(pScreenPriv); + + e->sisc = sisc; + e->siss = siss; + e->off = siss->expand_off; + e->last = 0; +} + +static CARD32 * +sisExpandAlloc (SisExpand *e, + int nb) +{ + SisCardInfo *sisc = e->sisc; + SisScreenInfo *siss = e->siss; + SisPtr sis = sisc->sis; + CARD32 off; + + /* round up to alignment boundary */ + nb = (nb + SIS_MIN_PATTERN-1) & ~(SIS_MIN_PATTERN-1); + + off = e->off + e->last; + if (off + nb > siss->expand_off + siss->expand_len) + { + _sisWaitIdleEmpty (sis); + off = siss->expand_off; + } + e->off = off; + e->last = nb; + return (CARD32 *) (sisc->frameBuffer + off); +} + +void +sisGlyphBltClipped (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + Bool imageBlt) +{ + SetupSis(pDrawable->pScreen); + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + int height; + int width; + int xBack, yBack; + int hBack, wBack; + int nb, bwidth, nl; + FontPtr pfont = pGC->font; + CharInfoPtr pci; + CARD8 *bits8, b; + CARD16 *bits16; + CARD32 *bits32; + BoxPtr extents; + BoxRec bbox; + unsigned char alu; + CARD32 cmd; + SisExpand expand; + CARD32 *dst, d; + int nbytes; + int shift; + int x1, y1, x2, y2; + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pBox; + int nbox; + int rect_in; + int widthBlt; + CharInfoPtr *ppci; + + x += pDrawable->x; + y += pDrawable->y; + + if (imageBlt) + { + xBack = x; + yBack = y - FONTASCENT(pGC->font); + wBack = 0; + hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + if (hBack) + { + height = nglyph; + ppci = ppciInit; + while (height--) + wBack += (*ppci++)->metrics.characterWidth; + } + if (wBack < 0) + { + xBack = xBack + wBack; + wBack = -wBack; + } + if (hBack < 0) + { + yBack = yBack + hBack; + hBack = -hBack; + } + alu = GXcopy; + } + else + { + wBack = 0; + alu = pGC->alu; + } + + if (wBack) + { + _sisSetSolidRect (sis, pGC->bgPixel, GXcopy, cmd); + for (nbox = REGION_NUM_RECTS (pClip), + pBox = REGION_RECTS (pClip); + nbox--; + pBox++) + { + x1 = xBack; + x2 = xBack + wBack; + y1 = yBack; + y2 = yBack + hBack; + if (x1 < pBox->x1) x1 = pBox->x1; + if (x2 > pBox->x2) x2 = pBox->x2; + if (y1 < pBox->y1) y1 = pBox->y1; + if (y2 > pBox->y2) y2 = pBox->y2; + if (x1 < x2 && y1 < y2) + { + _sisRect (sis, x1, y1, x2 - x1, y2 - y1, cmd); + } + } + } + + sisExpandInit (pDrawable->pScreen, &expand); + + sis->u.general.src_fg = pGC->fgPixel; + sis->u.general.src_pitch = 0; + sis->u.general.src_x = 0; + sis->u.general.src_y = 0; + + cmd = (SIS_CMD_ENH_COLOR_EXPAND | + SIS_CMD_SRC_SCREEN | + SIS_CMD_PAT_FG | + (sisBltRop[alu] << 8) | + SIS_CMD_INC_X | + SIS_CMD_INC_Y | + SIS_CMD_RECT_CLIP_ENABLE | + SIS_CMD_TRANSPARENT); + + ppci = ppciInit; + while (nglyph--) + { + pci = *ppci++; + height = pci->metrics.ascent + pci->metrics.descent; + width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + widthBlt = (width + 31) & ~31; + nb = (widthBlt >> 3) * height; + if (nb) + { + x1 = x + pci->metrics.leftSideBearing; + y1 = y - pci->metrics.ascent; + bbox.x1 = x1; + bbox.y1 = y1; + bbox.x2 = x1 + width; + bbox.y2 = y1 + height; + rect_in = RECT_IN_REGION(pGC->pScreen, pClip, &bbox); + if (rect_in != rgnOUT) + { + dst = sisExpandAlloc (&expand, nb); + + sis->u.general.src_base = expand.off; + sis->u.general.dst_x = x1; + sis->u.general.dst_y = y1; + sis->u.general.rect_width = widthBlt; + sis->u.general.rect_height = height; + nb >>= 2; + bits32 = (CARD32 *) pci->bits; + while (nb--) + { + d = *bits32++; + SisInvertBits32 (d); + *dst++ = d; + } + if (rect_in == rgnPART) + { + for (nbox = REGION_NUM_RECTS (pClip), + pBox = REGION_RECTS (pClip); + nbox--; + pBox++) + { + _sisClip (sis, pBox->x1, pBox->y1, pBox->x2, pBox->y2); + sis->u.general.command = cmd; + } + } + else + { + _sisClip (sis, 0, 0, x1+width, pScreenPriv->screen->height); + sis->u.general.command = cmd; + } + } + } + x += pci->metrics.characterWidth; + } + _sisClip (sis, 0, 0, + pScreenPriv->screen->width, pScreenPriv->screen->height); + KdMarkSync (pDrawable->pScreen); +} + +Bool +sisTEGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int xInit, + int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + Bool imageBlt) +{ + SetupSis(pDrawable->pScreen); + int x, y; + int widthGlyphs, widthGlyph; + int widthBlt; + FbBits depthMask; + int glyphsPer; + FontPtr pfont = pGC->font; + unsigned long *char1, *char2, *char3, *char4, *char5; + CARD8 alu; + CARD32 *dst, tmp; + CARD8 *dst8, *bits8; + int nb; + int bwidth; + CARD32 cmd; + int h; + BoxRec bbox; + SisExpand expand; + int lwTmp, lw; + int extra, n; + + widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); + if (!widthGlyph) + return TRUE; + + h = FONTASCENT(pfont) + FONTDESCENT(pfont); + if (!h) + return TRUE; + + x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing) + pDrawable->x; + y = yInit - FONTASCENT(pfont) + pDrawable->y; + + bbox.x1 = x; + bbox.x2 = x + (widthGlyph * nglyph); + bbox.y1 = y; + bbox.y2 = y + h; + + switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox)) + { + case rgnPART: + if (x < 0 || y < 0) + return FALSE; + sisGlyphBltClipped (pDrawable, pGC, xInit, yInit, nglyph, ppci, imageBlt); + case rgnOUT: + return TRUE; + } + + if (widthGlyph <= 6) + glyphsPer = 5; + else if (widthGlyph <= 8) + glyphsPer = 4; + else if (widthGlyph <= 10) + glyphsPer = 3; + else if (widthGlyph <= 16) + glyphsPer = 2; + else + glyphsPer = 1; + + widthGlyphs = widthGlyph * glyphsPer; + widthBlt = widthGlyphs; + + /* make sure scanlines are 32-bit aligned */ + if (widthGlyphs <= 24) + widthBlt = 25; + + cmd = (SIS_CMD_ENH_COLOR_EXPAND | + SIS_CMD_SRC_SCREEN | + SIS_CMD_PAT_FG | + SIS_CMD_INC_X | + SIS_CMD_INC_Y); + + if (imageBlt) + { + sis->u.general.clip_right = bbox.x2; + cmd |= ((sisBltRop[GXcopy] << 8) | + SIS_CMD_OPAQUE | + SIS_CMD_RECT_CLIP_ENABLE); + } + else + { + cmd |= ((sisBltRop[pGC->alu] << 8) | + SIS_CMD_TRANSPARENT | + SIS_CMD_RECT_CLIP_DISABLE); + } + + sisExpandInit (pDrawable->pScreen, &expand); + + sis->u.general.src_fg = pGC->fgPixel; + sis->u.general.src_bg = pGC->bgPixel; + + bwidth = (widthBlt + 7) >> 3; + + nb = bwidth * h; + +#define LoopIt(count, loadup, fetch) \ + while (nglyph >= count) \ + { \ + nglyph -= count; \ + dst = sisExpandAlloc (&expand, nb); \ + sis->u.general.src_base = expand.off; \ + sis->u.general.src_pitch = 0; \ + sis->u.general.src_x = 0; \ + sis->u.general.src_y = 0; \ + sis->u.general.dst_x = x; \ + sis->u.general.dst_y = y; \ + sis->u.general.rect_width = widthBlt; \ + sis->u.general.rect_height = h; \ + x += widthGlyphs; \ + loadup \ + lwTmp = h; \ + while (lwTmp--) { \ + tmp = fetch; \ + SisInvertBits32(tmp); \ + *dst++ = tmp; \ + } \ + sis->u.general.command = cmd; \ + } + + switch (glyphsPer) { + case 5: + LoopIt(5, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits; + char3 = (unsigned long *) (*ppci++)->bits; + char4 = (unsigned long *) (*ppci++)->bits; + char5 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | ((*char2++ | ((*char3++ | ((*char4++ | (*char5++ + << widthGlyph)) + << widthGlyph)) + << widthGlyph)) + << widthGlyph))); + break; + case 4: + LoopIt(4, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits; + char3 = (unsigned long *) (*ppci++)->bits; + char4 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | ((*char2++ | ((*char3++ | (*char4++ + << widthGlyph)) + << widthGlyph)) + << widthGlyph))); + break; + case 3: + LoopIt(3, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits; + char3 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | ((*char2++ | (*char3++ << widthGlyph)) << widthGlyph))); + break; + case 2: + LoopIt(2, + char1 = (unsigned long *) (*ppci++)->bits; + char2 = (unsigned long *) (*ppci++)->bits;, + (*char1++ | (*char2++ << widthGlyph))); + break; + } + + widthBlt = (widthGlyph + 31) & ~31; + + bwidth = widthBlt >> 3; + + nb = bwidth * h; + + lw = (widthBlt >> 5) * h; + + while (nglyph--) + { + dst = (CARD32 *) sisExpandAlloc (&expand, nb); + char1 = (CARD32 *) (*ppci++)->bits; + sis->u.general.src_base = expand.off; + sis->u.general.src_pitch = 0; + sis->u.general.src_x = 0; + sis->u.general.src_y = 0; + sis->u.general.dst_x = x; + sis->u.general.dst_y = y; + sis->u.general.rect_width = widthBlt; + sis->u.general.rect_height = h; + lwTmp = lw; + while (lwTmp--) + { + tmp = *char1++; + SisInvertBits32 (tmp); + *dst++ = tmp; + } + sis->u.general.command = cmd; + x += widthGlyph; + } + if (imageBlt) + sis->u.general.clip_right = pScreenPriv->screen->width; + KdMarkSync (pDrawable->pScreen); + return TRUE; +} + +Bool +sisGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppciInit, + Bool imageBlt) +{ + SetupSis(pDrawable->pScreen); + int height; + int width; + int xBack, yBack; + int hBack, wBack; + int nb, bwidth, nl; + FontPtr pfont = pGC->font; + CharInfoPtr pci; + CARD8 *bits8, b; + CARD16 *bits16; + CARD32 *bits32; + BoxPtr extents; + BoxRec bbox; + CharInfoPtr *ppci; + unsigned char alu; + CARD32 cmd; + SisExpand expand; + CARD32 *dst, d; + int nbytes; + int shift; + + x += pDrawable->x; + y += pDrawable->y; + + /* compute an approximate (but covering) bounding box */ + ppci = ppciInit; + width = 0; + height = nglyph; + while (height--) + width += (*ppci++)->metrics.characterWidth; + if (width < 0) + { + bbox.x1 = x + width; + bbox.x2 = x; + } + else + { + bbox.x1 = x; + bbox.x2 = x + width; + } + width = FONTMINBOUNDS(pfont,leftSideBearing); + if (width < 0) + bbox.x1 += width; + width = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth); + if (width > 0) + bbox.x2 += width; + bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent); + bbox.y2 = y + FONTMAXBOUNDS(pfont,descent); + + switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox)) + { + case rgnPART: + if (bbox.x1 < 0 || bbox.y1 < 0) + return FALSE; + sisGlyphBltClipped (pDrawable, pGC, + x - pDrawable->x, y - pDrawable->y, + nglyph, ppciInit, imageBlt); + case rgnOUT: + return TRUE; + } + + if (imageBlt) + { + xBack = x; + yBack = y - FONTASCENT(pGC->font); + wBack = 0; + hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + if (hBack) + { + height = nglyph; + ppci = ppciInit; + while (height--) + wBack += (*ppci++)->metrics.characterWidth; + } + if (wBack < 0) + { + xBack = xBack + wBack; + wBack = -wBack; + } + if (hBack < 0) + { + yBack = yBack + hBack; + hBack = -hBack; + } + alu = GXcopy; + } + else + { + wBack = 0; + alu = pGC->alu; + } + + if (wBack) + { + _sisSetSolidRect (sis, pGC->bgPixel, GXcopy, cmd); + _sisRect (sis, xBack, yBack, wBack, hBack, cmd); + } + + sisExpandInit (pDrawable->pScreen, &expand); + + sis->u.general.src_fg = pGC->fgPixel; + + cmd = (SIS_CMD_ENH_COLOR_EXPAND | + SIS_CMD_SRC_SCREEN | + SIS_CMD_PAT_FG | + (sisBltRop[alu] << 8) | + SIS_CMD_INC_X | + SIS_CMD_INC_Y | + SIS_CMD_RECT_CLIP_DISABLE | + SIS_CMD_TRANSPARENT); + + ppci = ppciInit; + while (nglyph--) + { + pci = *ppci++; + height = pci->metrics.ascent + pci->metrics.descent; + width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + /* + * For glyphs wider than 16 pixels, expand the blt to the nearest multiple + * of 32; this allows the scanlines to be padded to a 32-bit boundary + * instead of requiring byte packing + */ + if (width > 16) + width = (width + 31) & ~31; + bwidth = (width + 7) >> 3; + nb = bwidth * height; + if (nb) + { + dst = sisExpandAlloc (&expand, nb); + + sis->u.general.src_base = expand.off; + sis->u.general.src_pitch = 0; + sis->u.general.src_x = 0; + sis->u.general.src_y = 0; + sis->u.general.dst_x = x + pci->metrics.leftSideBearing; + sis->u.general.dst_y = y - pci->metrics.ascent; + sis->u.general.rect_width = width; + sis->u.general.rect_height = height; + switch (bwidth) { + case 1: + bits8 = (CARD8 *) pci->bits; + while (height >= 4) + { + d = (bits8[0] | (bits8[4] << 8) | + (bits8[8] << 16) | (bits8[12] << 24)); + SisInvertBits32(d); + *dst++ = d; + bits8 += 16; + height -= 4; + } + if (height) + { + switch (height) { + case 3: + d = bits8[0] | (bits8[4] << 8) | (bits8[8] << 16); + break; + case 2: + d = bits8[0] | (bits8[4] << 8); + break; + case 1: + d = bits8[0]; + break; + } + SisInvertBits32(d); + *dst++ = d; + } + break; + case 2: + bits16 = (CARD16 *) pci->bits; + while (height >= 2) + { + d = bits16[0] | (bits16[2] << 16); + SisInvertBits32(d); + *dst++ = d; + bits16 += 4; + height -= 2; + } + if (height) + { + d = bits16[0]; + SisInvertBits32(d); + *dst++ = d; + } + break; + default: + nb >>= 2; + bits32 = (CARD32 *) pci->bits; + while (nb--) + { + d = *bits32++; + SisInvertBits32 (d); + *dst++ = d; + } + } + sis->u.general.command = cmd; + } + x += pci->metrics.characterWidth; + } + KdMarkSync (pDrawable->pScreen); + return TRUE; +} +/* + * Blt glyphs using Sis image transfer register, this does both + * poly glyph blt and image glyph blt (when pglyphBase == 1) + */ + +void +sisPolyGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + FbBits depthMask; + + depthMask = FbFullMask (pDrawable->depth); + if ((pGC->planemask & depthMask) == depthMask && + pGC->fillStyle == FillSolid) + { + if (TERMINALFONT(pGC->font)) + { + if (sisTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE)) + return; + } + else + { + if (sisGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE)) + return; + } + } + KdCheckPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); +} + +void +sisImageGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + FbBits depthMask; + + depthMask = FbFullMask (pDrawable->depth); + if ((pGC->planemask & depthMask) == depthMask) + { + if (TERMINALFONT(pGC->font)) + { + if (sisTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE)) + return; + } + else + { + if (sisGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE)) + return; + } + } + KdCheckImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); +} + +#define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3)) + +#define sisPatternDimOk(d) ((d) <= 8 && (((d) & ((d) - 1)) == 0)) + +BOOL +sisFillOk (GCPtr pGC) +{ + FbBits depthMask; + + depthMask = FbFullMask(pGC->depth); + if ((pGC->planemask & depthMask) != depthMask) + return FALSE; + switch (pGC->fillStyle) { + case FillSolid: + return TRUE; + case FillTiled: + return (sisPatternDimOk (pGC->tile.pixmap->drawable.width) && + sisPatternDimOk (pGC->tile.pixmap->drawable.height)); + case FillStippled: + case FillOpaqueStippled: + return (sisPatternDimOk (pGC->stipple->drawable.width) && + sisPatternDimOk (pGC->stipple->drawable.height)); + } +} + +CARD32 +sisStipplePrepare (DrawablePtr pDrawable, GCPtr pGC) +{ + SetupSis(pGC->pScreen); + PixmapPtr pStip = pGC->stipple; + int stipHeight = pStip->drawable.height; + int xRot, yRot; + int rot, stipX, stipY; + FbStip *stip, *stipEnd, bits; + FbStride stipStride; + int stipBpp; + int stipXoff, stipYoff; /* XXX assumed to be zero */ + int y; + CARD32 cmd; + + xRot = pGC->patOrg.x + pDrawable->x; + yRot = pGC->patOrg.y + pDrawable->y; + modulus (- yRot, stipHeight, stipY); + modulus (- xRot, FB_UNIT, stipX); + rot = stipX; + + fbGetStipDrawable (&pStip->drawable, stip, stipStride, stipBpp, stipXoff, stipYoff); + for (y = 0; y < 8; y++) + { + bits = stip[stipY<<1]; + FbRotLeft(bits, rot); + SisInvertBits32(bits); + sis->u.general.mask[y] = (CARD8) bits; + stipY++; + if (stipY == stipHeight) + stipY = 0; + } + sis->u.general.pattern_fg = pGC->fgPixel; + + cmd = (SIS_CMD_BITBLT | + SIS_CMD_SRC_SCREEN | + SIS_CMD_PAT_MONO | + (sisPatRop[pGC->alu] << 8) | + SIS_CMD_INC_X | + SIS_CMD_INC_Y | + SIS_CMD_RECT_CLIP_DISABLE | + SIS_CMD_RECT_CLIP_DONT_MERGE); + if (pGC->fillStyle == FillOpaqueStippled) + { + sis->u.general.pattern_bg = pGC->bgPixel; + cmd |= SIS_CMD_OPAQUE; + } + else + cmd |= SIS_CMD_TRANSPARENT; + return cmd; +} + +CARD32 +sisTilePrepare (PixmapPtr pTile, int xRot, int yRot, CARD8 alu) +{ + SetupSis(pTile->drawable.pScreen); + int tileHeight = pTile->drawable.height; + int tileWidth = pTile->drawable.width; + FbBits *tile; + FbStride tileStride; + int tileBpp; + int tileXoff, tileYoff; /* XXX assumed to be zero */ + + fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp, tileXoff, tileYoff); + + /* + * Tile the pattern register + */ + fbTile ((FbBits *) sis->u.general.pattern, + (8 * tileBpp) >> FB_SHIFT, + 0, + + 8 * tileBpp, 8, + + tile, + tileStride, + tileWidth * tileBpp, + tileHeight, + GXcopy, FB_ALLONES, tileBpp, + xRot * tileBpp, + yRot); + + return (SIS_CMD_BITBLT | + SIS_CMD_SRC_SCREEN | + SIS_CMD_PAT_PATTERN | + (sisPatRop[alu] << 8) | + SIS_CMD_INC_X | + SIS_CMD_INC_Y | + SIS_CMD_RECT_CLIP_DISABLE | + SIS_CMD_RECT_CLIP_DONT_MERGE); +} + +void +sisFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, + unsigned long pixel, int alu) +{ + SetupSis(pDrawable->pScreen); + CARD32 cmd; + + _sisSetSolidRect(sis,pixel,alu,cmd); + + while (nBox--) + { + _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); + pBox++; + } + KdMarkSync (pDrawable->pScreen); +} + +void +sisFillBoxStipple (DrawablePtr pDrawable, GCPtr pGC, + int nBox, BoxPtr pBox) +{ + SetupSis(pDrawable->pScreen); + CARD32 cmd; + + cmd = sisStipplePrepare (pDrawable, pGC); + + while (nBox--) + { + _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); + pBox++; + } + KdMarkSync (pDrawable->pScreen); +} + +void +sisFillBoxTiled (DrawablePtr pDrawable, + int nBox, BoxPtr pBox, + PixmapPtr pTile, int xRot, int yRot, CARD8 alu) +{ + SetupSis (pDrawable->pScreen); + CARD32 cmd; + + cmd = sisTilePrepare (pTile, xRot, yRot, alu); + + while (nBox--) + { + _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); + pBox++; + } + KdMarkSync (pDrawable->pScreen); +} + +/* + sisDoBitBlt + ============= + Bit Blit for all window to window blits. +*/ + +void +sisCopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupSis(pDstDrawable->pScreen); + int srcX, srcY, dstX, dstY; + int w, h; + CARD32 flags; + CARD32 cmd; + CARD8 alu; + + if (pGC) + { + alu = pGC->alu; + if (sourceInvarient (pGC->alu)) + { + sisFillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu); + return; + } + } + else + alu = GXcopy; + + _sisSetBlt(sis,alu,cmd); + while (nbox--) + { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + flags = 0; + if (reverse) + { + dstX = pbox->x2 - 1; + } + else + { + dstX = pbox->x1; + flags |= SIS_CMD_INC_X; + } + srcX = dstX + dx; + + if (upsidedown) + { + dstY = pbox->y2 - 1; + } + else + { + dstY = pbox->y1; + flags |= SIS_CMD_INC_Y; + } + srcY = dstY + dy; + + _sisBlt (sis, srcX, srcY, dstX, dstY, w, h, cmd|flags); + pbox++; + } + KdMarkSync (pDstDrawable->pScreen); +} + +RegionPtr +sisCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + KdScreenPriv(pDstDrawable->pScreen); + FbBits depthMask; + + depthMask = FbFullMask (pDstDrawable->depth); + if ((pGC->planemask & depthMask) == depthMask && + pSrcDrawable->type == DRAWABLE_WINDOW && + pDstDrawable->type == DRAWABLE_WINDOW) + { + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, sisCopyNtoN, 0, 0); + } + return KdCheckCopyArea (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty); +} + +typedef struct _sis1toNargs { + unsigned long copyPlaneFG, copyPlaneBG; +} sis1toNargs; + +void +_sisStipple (ScreenPtr pScreen, + FbStip *psrcBase, + FbStride widthSrc, + CARD8 alu, + int srcx, + int srcy, + int dstx, + int dsty, + int width, + int height) +{ + SetupSis(pScreen); + FbStip *psrcLine, *psrc; + FbStride widthRest; + FbStip bits, tmp, lastTmp; + int leftShift, rightShift; + int nl, nlMiddle; + int r; + SisExpand expand; + CARD32 *dst; + int hthis; + int hper; + int bwidth; + CARD32 cmd; + + sisExpandInit (pScreen, &expand); + + /* Compute blt address and parameters */ + psrc = psrcBase + srcy * widthSrc + (srcx >> 5); + nlMiddle = (width + 31) >> 5; + leftShift = srcx & 0x1f; + rightShift = 32 - leftShift; + widthRest = widthSrc - nlMiddle; + + cmd = (SIS_CMD_ENH_COLOR_EXPAND | + SIS_CMD_SRC_SCREEN | + SIS_CMD_PAT_FG | + (sisBltRop[alu] << 8) | + SIS_CMD_INC_X | + SIS_CMD_INC_Y | + SIS_CMD_OPAQUE | + SIS_CMD_RECT_CLIP_ENABLE); + + if (leftShift != 0) + widthRest--; + + sis->u.general.src_x = 0; + sis->u.general.src_y = 0; + sis->u.general.dst_x = dstx; + sis->u.general.rect_width = (width + 31) & ~31; + sis->u.general.clip_right = (dstx + width); + + bwidth = nlMiddle << 2; + hper = SIS_PATTERN_INC / bwidth; + if (hper == 0) + hper = 1; + + while (height) + { + hthis = hper; + if (hthis > height) + hthis = height; + dst = sisExpandAlloc (&expand, bwidth * hthis); + sis->u.general.src_base = expand.off; + sis->u.general.dst_y = dsty; + sis->u.general.rect_height = hthis; + + dsty += hthis; + height -= hthis; + + if (leftShift == 0) + { + while (hthis--) + { + nl = nlMiddle; + while (nl--) + { + tmp = *psrc++; + SisInvertBits32(tmp); + *dst++ = tmp; + } + psrc += widthRest; + } + } + else + { + while (hthis--) + { + bits = *psrc++; + nl = nlMiddle; + while (nl--) + { + tmp = FbStipLeft(bits, leftShift); + bits = *psrc++; + tmp |= FbStipRight(bits, rightShift); + SisInvertBits32(tmp); + *dst++ = tmp; + } + psrc += widthRest; + } + } + sis->u.general.command = cmd; + } + sis->u.general.clip_right = pScreenPriv->screen->width; +} + +void +sisCopy1toN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + SetupSis(pDstDrawable->pScreen); + + sis1toNargs *args = closure; + int dstx, dsty; + FbStip *psrcBase; + FbStride widthSrc; + int srcBpp; + int srcXoff, srcYoff; + + if (sourceInvarient (pGC->alu)) + { + sisFillBoxSolid (pDstDrawable, nbox, pbox, + pGC->bgPixel, pGC->alu); + return; + } + + fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp, srcXoff, srcYoff); + + sis->u.general.src_fg = args->copyPlaneFG; + sis->u.general.src_bg = args->copyPlaneBG; + + while (nbox--) + { + dstx = pbox->x1; + dsty = pbox->y1; + + _sisStipple (pDstDrawable->pScreen, + psrcBase, widthSrc, + pGC->alu, + dstx + dx - srcXoff, dsty + dy - srcYoff, + dstx, dsty, + pbox->x2 - dstx, pbox->y2 - dsty); + pbox++; + } + KdMarkSync (pDstDrawable->pScreen); +} + +RegionPtr +sisCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + KdScreenPriv (pDstDrawable->pScreen); + RegionPtr ret; + sis1toNargs args; + FbBits depthMask; + + depthMask = FbFullMask (pDstDrawable->depth); + if ((pGC->planemask & depthMask) == depthMask && + pDstDrawable->type == DRAWABLE_WINDOW && + pSrcDrawable->depth == 1) + { + args.copyPlaneFG = pGC->fgPixel; + args.copyPlaneBG = pGC->bgPixel; + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, sisCopy1toN, bitPlane, &args); + } + return KdCheckCopyPlane(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, bitPlane); +} + +void +sisFillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + SetupSis(pDrawable->pScreen); + DDXPointPtr pptFree; + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + int *pwidthFree;/* copies of the pointers to free */ + CARD32 cmd; + int nTmp; + INT16 x, y; + int width; + + if (!sisFillOk (pGC)) + { + KdCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); + return; + } + nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC)); + pwidthFree = (int *)xalloc(nTmp * sizeof(int)); + pptFree = (DDXPointRec *)xalloc(nTmp * sizeof(DDXPointRec)); + if(!pptFree || !pwidthFree) + { + if (pptFree) xfree(pptFree); + if (pwidthFree) xfree(pwidthFree); + return; + } + n = miClipSpans(fbGetCompositeClip(pGC), + ppt, pwidth, n, + pptFree, pwidthFree, fSorted); + pwidth = pwidthFree; + ppt = pptFree; + switch (pGC->fillStyle) { + case FillSolid: + _sisSetSolidRect(sis,pGC->fgPixel,pGC->alu,cmd); + break; + case FillTiled: + cmd = sisTilePrepare (pGC->tile.pixmap, + pGC->patOrg.x + pDrawable->x, + pGC->patOrg.y + pDrawable->y, + pGC->alu); + break; + default: + cmd = sisStipplePrepare (pDrawable, pGC); + break; + } + while (n--) + { + x = ppt->x; + y = ppt->y; + ppt++; + width = *pwidth++; + if (width) + { + _sisRect(sis,x,y,width,1,cmd); + } + } + KdMarkSync (pDrawable->pScreen); + xfree(pptFree); + xfree(pwidthFree); +} + +#define NUM_STACK_RECTS 1024 + +void +sisPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, + int nrectFill, xRectangle *prectInit) +{ + SetupSis(pDrawable->pScreen); + xRectangle *prect; + RegionPtr prgnClip; + register BoxPtr pbox; + register BoxPtr pboxClipped; + BoxPtr pboxClippedBase; + BoxPtr pextent; + BoxRec stackRects[NUM_STACK_RECTS]; + FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC); + int numRects; + int n; + int xorg, yorg; + int x, y; + + if (!sisFillOk (pGC)) + { + KdCheckPolyFillRect (pDrawable, pGC, nrectFill, prectInit); + return; + } + prgnClip = fbGetCompositeClip(pGC); + xorg = pDrawable->x; + yorg = pDrawable->y; + + if (xorg || yorg) + { + prect = prectInit; + n = nrectFill; + while(n--) + { + prect->x += xorg; + prect->y += yorg; + prect++; + } + } + + prect = prectInit; + + numRects = REGION_NUM_RECTS(prgnClip) * nrectFill; + if (numRects > NUM_STACK_RECTS) + { + pboxClippedBase = (BoxPtr)xalloc(numRects * sizeof(BoxRec)); + if (!pboxClippedBase) + return; + } + else + pboxClippedBase = stackRects; + + pboxClipped = pboxClippedBase; + + if (REGION_NUM_RECTS(prgnClip) == 1) + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_RECTS(prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + if ((pboxClipped->x1 = prect->x) < x1) + pboxClipped->x1 = x1; + + if ((pboxClipped->y1 = prect->y) < y1) + pboxClipped->y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + pboxClipped->x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + pboxClipped->y2 = by2; + + prect++; + if ((pboxClipped->x1 < pboxClipped->x2) && + (pboxClipped->y1 < pboxClipped->y2)) + { + pboxClipped++; + } + } + } + else + { + int x1, y1, x2, y2, bx2, by2; + + pextent = REGION_EXTENTS(pGC->pScreen, prgnClip); + x1 = pextent->x1; + y1 = pextent->y1; + x2 = pextent->x2; + y2 = pextent->y2; + while (nrectFill--) + { + BoxRec box; + + if ((box.x1 = prect->x) < x1) + box.x1 = x1; + + if ((box.y1 = prect->y) < y1) + box.y1 = y1; + + bx2 = (int) prect->x + (int) prect->width; + if (bx2 > x2) + bx2 = x2; + box.x2 = bx2; + + by2 = (int) prect->y + (int) prect->height; + if (by2 > y2) + by2 = y2; + box.y2 = by2; + + prect++; + + if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) + continue; + + n = REGION_NUM_RECTS (prgnClip); + pbox = REGION_RECTS(prgnClip); + + /* clip the rectangle to each box in the clip region + this is logically equivalent to calling Intersect() + */ + while(n--) + { + pboxClipped->x1 = max(box.x1, pbox->x1); + pboxClipped->y1 = max(box.y1, pbox->y1); + pboxClipped->x2 = min(box.x2, pbox->x2); + pboxClipped->y2 = min(box.y2, pbox->y2); + pbox++; + + /* see if clipping left anything */ + if(pboxClipped->x1 < pboxClipped->x2 && + pboxClipped->y1 < pboxClipped->y2) + { + pboxClipped++; + } + } + } + } + if (pboxClipped != pboxClippedBase) + { + switch (pGC->fillStyle) { + case FillSolid: + sisFillBoxSolid(pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->fgPixel, pGC->alu); + break; + case FillTiled: + sisFillBoxTiled(pDrawable, + pboxClipped-pboxClippedBase, pboxClippedBase, + pGC->tile.pixmap, + pGC->patOrg.x + pDrawable->x, + pGC->patOrg.y + pDrawable->y, + pGC->alu); + break; + case FillStippled: + case FillOpaqueStippled: + sisFillBoxStipple (pDrawable, pGC, + pboxClipped-pboxClippedBase, pboxClippedBase); + break; + } + } + if (pboxClippedBase != stackRects) + xfree(pboxClippedBase); +} + +static const GCOps sisOps = { + sisFillSpans, + KdCheckSetSpans, + KdCheckPutImage, + sisCopyArea, + sisCopyPlane, + KdCheckPolyPoint, + KdCheckPolylines, + KdCheckPolySegment, + miPolyRectangle, + KdCheckPolyArc, + miFillPolygon, + sisPolyFillRect, + KdCheckPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + sisImageGlyphBlt, + sisPolyGlyphBlt, + KdCheckPushPixels, +}; + +void +sisValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) +{ + FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); + + fbValidateGC (pGC, changes, pDrawable); + + if (pDrawable->type == DRAWABLE_WINDOW) + pGC->ops = (GCOps *) &sisOps; + else + pGC->ops = (GCOps *) &kdAsyncPixmapGCOps; +} + +GCFuncs sisGCFuncs = { + sisValidateGC, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip +}; + +int +sisCreateGC (GCPtr pGC) +{ + if (!fbCreateGC (pGC)) + return FALSE; + + if (pGC->depth != 1) + pGC->funcs = &sisGCFuncs; + + pGC->ops = (GCOps *) &kdAsyncPixmapGCOps; + + return TRUE; +} + +void +sisCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KdScreenPriv(pScreen); + RegionRec rgnDst; + int dx, dy; + WindowPtr pwinRoot; + + pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); + + REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); + + REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + 0, + &rgnDst, dx, dy, sisCopyNtoN, 0, 0); + + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); +} + +Bool +sisDrawInit (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + sisScreenInfo(pScreenPriv); + + /* + * Hook up asynchronous drawing + */ + KdScreenInitAsync (pScreen); + /* + * Replace various fb screen functions + */ + pScreen->CreateGC = sisCreateGC; + pScreen->CopyWindow = sisCopyWindow; + + return TRUE; +} + +void +sisDrawEnable (ScreenPtr pScreen) +{ + SetupSis(pScreen); + sisScreenInfo(pScreenPriv); + CARD32 cmd; + CARD32 base; + CARD16 stride; + CARD16 op; + + base = pScreenPriv->screen->fb[0].frameBuffer - sisc->frameBuffer; + stride = pScreenPriv->screen->fb[0].byteStride; +#if 0 + sis->u.general.dst_base = base; + sis->u.general.dst_pitch = stride; + sis->u.general.src_pitch = stride; + sis->u.general._pad0 = stride; + sis->u.general.dst_height = pScreenPriv->screen->height; + _sisClip (sis, 0, 0, + pScreenPriv->screen->width, pScreenPriv->screen->height); + _sisSetSolidRect(sis, pScreen->blackPixel, GXcopy, cmd); + _sisRect (sis, 0, 0, + pScreenPriv->screen->width, pScreenPriv->screen->height, + cmd); +#endif + base = (CARD32) (pScreenPriv->screen->fb[0].frameBuffer); + fprintf (stderr, "src 0x%x\n", sis->u.accel.src_addr); + sis->u.accel.src_addr = (base & 0x3fffff); + fprintf (stderr, "src 0x%x\n", sis->u.accel.src_addr); + sis->u.accel.dst_addr = (base & 0x3fffff); + sis->u.accel.pitch = (stride << 16) | stride; + sis->u.accel.dimension = ((pScreenPriv->screen->height-1) << 16 | + (pScreenPriv->screen->width - 1)); + sis->u.accel.fg = (sisBltRop[GXcopy] << 24) | 0xf800; + sis->u.accel.bg = (sisBltRop[GXcopy] << 24) | 0x00; + +#define sisLEFT2RIGHT 0x10 +#define sisRIGHT2LEFT 0x00 +#define sisTOP2BOTTOM 0x20 +#define sisBOTTOM2TOP 0x00 + +#define sisSRCSYSTEM 0x03 +#define sisSRCVIDEO 0x02 +#define sisSRCFG 0x01 +#define sisSRCBG 0x00 + +#define sisCMDBLT 0x0000 +#define sisCMDBLTMSK 0x0100 +#define sisCMDCOLEXP 0x0200 +#define sisCMDLINE 0x0300 + +#define sisCMDENHCOLEXP 0x2000 + +#define sisXINCREASE 0x10 +#define sisYINCREASE 0x20 +#define sisCLIPENABL 0x40 +#define sisCLIPINTRN 0x80 +#define sisCLIPEXTRN 0x00 + + +#define sisPATREG 0x08 +#define sisPATFG 0x04 +#define sisPATBG 0x00 + +#define sisLASTPIX 0x0800 +#define sisXMAJOR 0x0400 + + op = sisCMDBLT | sisLEFT2RIGHT | sisTOP2BOTTOM | sisSRCFG | sisPATFG; + + sis->u.accel.cmd = op; + + KdMarkSync (pScreen); +} + +void +sisDrawSync (ScreenPtr pScreen) +{ + SetupSis(pScreen); + + _sisWaitIdleEmpty (sis); +} + +void +sisDrawDisable (ScreenPtr pScreen) +{ +} + +void +sisDrawFini (ScreenPtr pScreen) +{ +} diff --git a/xserver/hw/kdrive/sis530/sisdraw.h b/xserver/hw/kdrive/sis530/sisdraw.h new file mode 100644 index 000000000..971ad64ac --- /dev/null +++ b/xserver/hw/kdrive/sis530/sisdraw.h @@ -0,0 +1,180 @@ +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, 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. + */ + +#ifndef _SISDRAW_H_ +#define _SISDRAW_H_ + +#define SetupSis(s) KdScreenPriv(s); \ + sisCardInfo(pScreenPriv); \ + SisPtr sis = sisc->sis + +#define SIS_CMD_BITBLT (0) +#define SIS_CMD_COLOR_EXPAND (1) +#define SIS_CMD_ENH_COLOR_EXPAND (2) +#define SIS_CMD_MULTI_SCANLINE (3) +#define SIS_CMD_LINE (4) +#define SIS_CMD_TRAPEZOID (5) +#define SIS_CMD_TRANSPARENT_BITBLT (6) + +#define SIS_CMD_SRC_SCREEN (0 << 4) +#define SIS_CMD_SRC_CPU (1 << 4) + +#define SIS_CMD_PAT_FG (0 << 6) +#define SIS_CMD_PAT_PATTERN (1 << 6) +#define SIS_CMD_PAT_MONO (2 << 6) + +/* 8->15 rop */ + +#define SIS_CMD_DEC_X (0 << 16) +#define SIS_CMD_INC_X (1 << 16) + +#define SIS_CMD_DEC_Y (0 << 17) +#define SIS_CMD_INC_Y (1 << 17) + +#define SIS_CMD_RECT_CLIP_DISABLE (0 << 18) +#define SIS_CMD_RECT_CLIP_ENABLE (1 << 18) + +#define SIS_CMD_OPAQUE (0 << 20) +#define SIS_CMD_TRANSPARENT (1 << 20) + +#define SIS_CMD_RECT_CLIP_MERGE (0 << 26) +#define SIS_CMD_RECT_CLIP_DONT_MERGE (1 << 26) + +#define SIS_STAT_2D_IDLE (1 << 31) +#define SIS_STAT_3D_IDLE (1 << 30) +#define SIS_STAT_EMPTY (1 << 29) +#define SIS_STAT_CPU_BITBLT (0xf << 24) +#define SIS_STAT_ENH_COLOR_EXPAND (1 << 23) +#define SIS_STAT_AVAIL (0x1fff) + +extern CARD8 sisPatRop[16]; +extern CARD8 sisBltRop[16]; + +#define _sisSetSolidRect(sis,pix,alu,cmd) {\ + (sis)->u.general.pattern_fg = (pix); \ + (cmd) = (SIS_CMD_BITBLT | \ + SIS_CMD_SRC_SCREEN | \ + SIS_CMD_PAT_FG | \ + (sisPatRop[alu] << 8) | \ + SIS_CMD_INC_X | \ + SIS_CMD_INC_Y | \ + SIS_CMD_RECT_CLIP_DISABLE | \ + SIS_CMD_OPAQUE | \ + SIS_CMD_RECT_CLIP_DONT_MERGE); \ +} + +#define _sisClip(sis,x1,y1,x2,y2) { \ + (sis)->u.general.clip_left = (x1); \ + (sis)->u.general.clip_top = (y1); \ + (sis)->u.general.clip_right = (x2); \ + (sis)->u.general.clip_bottom = (y2); \ +} + +#define _sisRect(sis,x,y,w,h,cmd) { \ + (sis)->u.general.dst_x = (x); \ + (sis)->u.general.dst_y = (y); \ + (sis)->u.general.rect_width = (w); \ + (sis)->u.general.rect_height = (h); \ + (sis)->u.general.command = (cmd); \ +} + +#define _sisSetTransparentPlaneBlt(sis, alu, fg, cmd) { \ + (sis)->u.general.src_fg = (fg); \ + (cmd) = (SIS_CMD_ENH_COLOR_EXPAND | \ + SIS_CMD_SRC_CPU | \ + SIS_CMD_PAT_FG | \ + (sisBltRop[alu] << 8) | \ + SIS_CMD_INC_X | \ + SIS_CMD_INC_Y | \ + SIS_CMD_RECT_CLIP_DISABLE | \ + SIS_CMD_TRANSPARENT | \ + SIS_CMD_RECT_CLIP_DONT_MERGE); \ +} + +#define _sisSetOpaquePlaneBlt(sis, alu, fg, bg, cmd) { \ + (sis)->u.general.src_fg = (fg); \ + (sis)->u.general.src_bg = (bg); \ + (cmd) = (SIS_CMD_ENH_COLOR_EXPAND | \ + SIS_CMD_SRC_CPU | \ + SIS_CMD_PAT_FG | \ + (sisBltRop[alu] << 8) | \ + SIS_CMD_INC_X | \ + SIS_CMD_INC_Y | \ + SIS_CMD_RECT_CLIP_DISABLE | \ + SIS_CMD_OPAQUE | \ + SIS_CMD_RECT_CLIP_DONT_MERGE); \ +} + +#define _sisPlaneBlt(sis,x,y,w,h,cmd) _sisSolidRect(sis,x,y,w,h,cmd) + +#define _sisSetBlt(sis,alu,cmd) { \ + (sis)->u.general.src_base = (sis)->u.general.dst_base; \ + (sis)->u.general.src_pitch = (sis)->u.general.dst_pitch; \ + (cmd) = (SIS_CMD_RECT_CLIP_DONT_MERGE |\ + (sisBltRop[alu] << 8) |\ + SIS_CMD_PAT_FG |\ + SIS_CMD_SRC_SCREEN |\ + SIS_CMD_BITBLT); \ +} + +#define _sisBlt(sis,sx,sy,dx,dy,w,h,cmd) { \ + (sis)->u.general.src_x = (sx); \ + (sis)->u.general.src_y = (sy); \ + (sis)->u.general.dst_x = (dx); \ + (sis)->u.general.dst_y = (dy); \ + (sis)->u.general.rect_width = (w); \ + (sis)->u.general.rect_height = (h); \ + (sis)->u.general.command = (cmd); \ +} + +#define SIS_IE (SIS_STAT_2D_IDLE|SIS_STAT_EMPTY) + +#define _sisWaitIdleEmpty(sis) \ + while (((sis)->u.general.status & SIS_IE) != SIS_IE) + +/* + * Ok, so the Sis530 is broken -- it expects bitmaps to come MSB bit order, + * but it's willing to take them in LSB byte order. These macros + * flip bits around without flipping bytes. Instead of using a table + * and burning memory bandwidth, do them in place with the CPU. + */ + +/* The MIPS compiler automatically places these constants in registers */ +#define SisInvertBits32(v) { \ + v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \ + v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \ + v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \ +} + +#define SisInvertBits16(v) { \ + v = ((v & 0x5555) << 1) | ((v >> 1) & 0x5555); \ + v = ((v & 0x3333) << 2) | ((v >> 2) & 0x3333); \ + v = ((v & 0x0f0f) << 4) | ((v >> 4) & 0x0f0f); \ +} + +#define SisInvertBits8(v) { \ + v = ((v & 0x55) << 1) | ((v >> 1) & 0x55); \ + v = ((v & 0x33) << 2) | ((v >> 2) & 0x33); \ + v = ((v & 0x0f) << 4) | ((v >> 4) & 0x0f); \ +} + +#endif diff --git a/xserver/hw/kdrive/sis530/sisio.c b/xserver/hw/kdrive/sis530/sisio.c new file mode 100644 index 000000000..4741937a4 --- /dev/null +++ b/xserver/hw/kdrive/sis530/sisio.c @@ -0,0 +1,30 @@ +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, 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. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#ifdef linux +#define extern +#include <asm/io.h> +#undef extern +#endif diff --git a/xserver/hw/kdrive/sis530/sisstub.c b/xserver/hw/kdrive/sis530/sisstub.c new file mode 100644 index 000000000..960510bff --- /dev/null +++ b/xserver/hw/kdrive/sis530/sisstub.c @@ -0,0 +1,67 @@ +/* + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, 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. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "sis.h" + +static const int sisCards[] = { 0x6306, 0x0200 }; + +#define numSisCards (sizeof (sisCards) / sizeof (sisCards[0])) + +void +InitCard (char *name) +{ + KdCardAttr attr; + int i; + + for (i = 0; i < numSisCards; i++) + if (LinuxFindPci (0x1039, sisCards[i], 0, &attr)) + KdCardInfoAdd (&sisFuncs, &attr, (void *) sisCards[i]); +} + +void +InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv) +{ + KdInitOutput (pScreenInfo, argc, argv); +} + +void +InitInput (int argc, char **argv) +{ + KdOsAddInputDrivers (); + KdInitInput (); +} + +void +ddxUseMsg (void) +{ + KdUseMsg(); +} + +int +ddxProcessArgument (int argc, char **argv, int i) +{ + return KdProcessArgument (argc, argv, i); +} |