diff options
Diffstat (limited to 'hw/kdrive/src/vga.c')
-rw-r--r-- | hw/kdrive/src/vga.c | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/hw/kdrive/src/vga.c b/hw/kdrive/src/vga.c new file mode 100644 index 000000000..0e0c53878 --- /dev/null +++ b/hw/kdrive/src/vga.c @@ -0,0 +1,288 @@ +/* + * $Id$ + * + * 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. + */ +/* $XFree86: $ */ + +#include "vga.h" +#include <stdio.h> + +#ifdef linux +#define extern +#include <asm/io.h> +#undef extern + +#define _VgaInb(r) inb(r) +#define _VgaOutb(v,r) outb(v,r) + +#endif + +#if 0 +#define VGA_DEBUG(a) fprintf a +#else +#define VGA_DEBUG(a) +#endif + +VGA8 +VgaInb (VGA16 r) +{ + return _VgaInb(r); +} + +void +VgaOutb (VGA8 v, VGA16 r) +{ + _VgaOutb (v,r); +} + +VGA8 +VgaFetch (VgaCard *card, VGA16 reg) +{ + VgaMap map; + VGAVOL8 *mem; + VGA8 value; + + (*card->map) (card, reg, &map, VGAFALSE); + switch (map.access) { + case VgaAccessMem: + mem = (VGAVOL8 *) map.port; + value = *mem; + break; + case VgaAccessIo: + value = _VgaInb (map.port); + VGA_DEBUG ((stderr, "%4x -> %2x\n", map.port, value)); + break; + case VgaAccessIndMem: + mem = (VGAVOL8 *) map.port; + mem[map.addr] = map.index; + value = mem[map.value]; + break; + case VgaAccessIndIo: + _VgaOutb (map.index, map.port + map.addr); + value = _VgaInb (map.port + map.value); + VGA_DEBUG ((stderr, "%4x/%2x -> %2x\n", map.port, map.index, value)); + break; + case VgaAccessDone: + value = map.value; + VGA_DEBUG ((stderr, "direct %4x -> %2x\n", reg, value)); + break; + } + return value; +} + +void +VgaStore (VgaCard *card, VGA16 reg, VGA8 value) +{ + VgaMap map; + VGAVOL8 *mem; + + map.value = value; + (*card->map) (card, reg, &map, VGATRUE); + switch (map.access) { + case VgaAccessMem: + mem = (VGAVOL8 *) map.port; + *mem = value; + break; + case VgaAccessIo: + VGA_DEBUG ((stderr, "%4x <- %2x\n", map.port, value)); + _VgaOutb (value, map.port); + break; + case VgaAccessIndMem: + mem = (VGAVOL8 *) map.port; + mem[map.addr] = map.index; + mem[map.value] = value; + break; + case VgaAccessIndIo: + VGA_DEBUG ((stderr, "%4x/%2x <- %2x\n", map.port, map.index, value)); + _VgaOutb (map.index, map.port + map.addr); + _VgaOutb (value, map.port + map.value); + break; + case VgaAccessDone: + VGA_DEBUG ((stderr, "direct %4x <- %2x\n", reg, value)); + break; + } +} + +void +VgaPreserve (VgaCard *card) +{ + VgaSave *s; + VGA16 id; + + for (s = card->saves; s->first != VGA_REG_NONE; s++) + { + for (id = s->first; id <= s->last; id++) + { + card->values[id].cur = VgaFetch (card, id); + card->values[id].save = card->values[id].cur; + card->values[id].flags = VGA_VALUE_VALID | VGA_VALUE_SAVED; + } + } +} + +void +VgaRestore (VgaCard *card) +{ + VgaSave *s; + VGA16 id; + + for (s = card->saves; s->first != VGA_REG_NONE; s++) + { + for (id = s->first; id <= s->last; id++) + { + if (card->values[id].flags & VGA_VALUE_SAVED) + { + VgaStore (card, id, card->values[id].save); + card->values[id].cur = card->values[id].save; + } + } + } +} + +void +VgaFinish (VgaCard *card) +{ + VGA16 id; + + for (id = 0; id < card->max; id++) + card->values[id].flags = 0; +} + +void +_VgaSync (VgaCard *card, VGA16 id) +{ + if (!(card->values[id].flags & VGA_VALUE_VALID)) + { + card->values[id].cur = VgaFetch (card, id); + card->values[id].flags |= VGA_VALUE_VALID; + } +} + +void +VgaSet (VgaCard *card, VgaReg *reg, VGA32 value) +{ + VGA8 v, mask, new; + + while (reg->len) + { + if (reg->id != VGA_REG_NONE) + { + _VgaSync (card, reg->id); + mask = ((1 << reg->len) - 1); + new = value & mask; + mask <<= reg->base; + new <<= reg->base; + v = card->values[reg->id].cur; + v = v & ~mask | new; + card->values[reg->id].cur = v; + card->values[reg->id].flags |= VGA_VALUE_MODIFIED|VGA_VALUE_DIRTY; + } + value >>= reg->len; + reg++; + } +} + +void +VgaFlushReg (VgaCard *card, VgaReg *reg) +{ + while (reg->len) + { + if (reg->id != VGA_REG_NONE) + { + if (card->values[reg->id].flags & VGA_VALUE_DIRTY) + { + VgaStore (card, reg->id, card->values[reg->id].cur); + card->values[reg->id].flags &= ~VGA_VALUE_DIRTY; + } + } + reg++; + } + +} + +void +VgaSetImm (VgaCard *card, VgaReg *reg, VGA32 value) +{ + VgaSet (card, reg, value); + VgaFlushReg (card, reg); +} + +VGA32 +VgaGet (VgaCard *card, VgaReg *reg) +{ + VGA32 value, offset, v; + VGA8 mask; + + value = 0; + offset = 0; + while (reg->len) + { + if (reg->id != VGA_REG_NONE) + { + _VgaSync (card, reg->id); + mask = ((1 << reg->len) - 1); + v = (card->values[reg->id].cur >> reg->base) & mask; + value |= (v << offset); + } + offset += reg->len; + reg++; + } + return value; +} + +VGA32 +VgaGetImm (VgaCard *card, VgaReg *reg) +{ + VgaReg *r = reg; + + while (r->len) + { + if (r->id != VGA_REG_NONE) + card->values[r->id].flags &= ~VGA_VALUE_VALID; + r++; + } + return VgaGet (card, reg); +} + +void +VgaFlush (VgaCard *card) +{ + VGA16 id; + + for (id = 0; id < card->max; id++) + { + if (card->values[id].flags & VGA_VALUE_DIRTY) + { + VgaStore (card, id, card->values[id].cur); + card->values[id].flags &= ~VGA_VALUE_DIRTY; + } + } +} + +void +VgaFill (VgaCard *card, VGA16 low, VGA16 high) +{ + VGA16 id; + + for (id = low; id < high; id++) + _VgaSync (card, id); +} |