/* * $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 #ifdef linux #define extern #include #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); }