diff options
Diffstat (limited to 'src/i830_ring.h')
-rw-r--r-- | src/i830_ring.h | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/i830_ring.h b/src/i830_ring.h new file mode 100644 index 00000000..177b0d52 --- /dev/null +++ b/src/i830_ring.h @@ -0,0 +1,135 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright © 2002 David Dawes + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef _INTEL_RING_H +#define _INTEL_RING_H + +#define OUT_RING(n) do { \ + if (I810_DEBUG & DEBUG_VERBOSE_RING) \ + ErrorF("OUT_RING 0x%08x: 0x%08x, (mask %x)\n", \ + pI830->ring_next, (unsigned int)(n), \ + pI830->LpRing->tail_mask); \ + *(volatile uint32_t *)(pI830->LpRing->virtual_start + \ + pI830->ring_next) = n; \ + pI830->ring_used += 4; \ + pI830->ring_next += 4; \ + pI830->ring_next &= pI830->LpRing->tail_mask; \ +} while (0) + +/** Copies a given number of bytes to the ring */ +#define OUT_RING_COPY(n, ptr) do { \ + if (I810_DEBUG & DEBUG_VERBOSE_RING) \ + ErrorF("OUT_RING_DATA %d bytes\n", n); \ + memcpy_volatile(pI830->LpRing->virtual_start + pI830->ring_next, \ + ptr, n); \ + pI830->ring_used += n; \ + pI830->ring_next += n; \ + pI830->ring_next &= pI830->LpRing->tail_mask; \ +} while (0) + +/** Pads the ring with a given number of zero bytes */ +#define OUT_RING_PAD(n) do { \ + if (I810_DEBUG & DEBUG_VERBOSE_RING) \ + ErrorF("OUT_RING_PAD %d bytes\n", n); \ + memset_volatile(pI830->LpRing->virtual_start + pI830->ring_next, \ + 0, n); \ + pI830->ring_used += n; \ + pI830->ring_next += n; \ + pI830->ring_next &= pI830->LpRing->tail_mask; \ +} while (0) + +union intfloat { + float f; + unsigned int ui; +}; + +#define OUT_RING_F(x) do { \ + union intfloat tmp; \ + tmp.f = (float)(x); \ + OUT_RING(tmp.ui); \ +} while(0) + +#define ADVANCE_LP_RING() do { \ + if (pI830->ring_emitting == 0) \ + FatalError("%s: ADVANCE_LP_RING called with no matching " \ + "BEGIN_LP_RING\n", __FUNCTION__); \ + if (pI830->ring_used > pI830->ring_emitting) \ + FatalError("%s: ADVANCE_LP_RING: exceeded allocation %d/%d\n ", \ + __FUNCTION__, pI830->ring_used, \ + pI830->ring_emitting); \ + if (pI830->ring_used < pI830->ring_emitting) \ + FatalError("%s: ADVANCE_LP_RING: under-used allocation %d/%d\n ", \ + __FUNCTION__, pI830->ring_used, \ + pI830->ring_emitting); \ + pI830->LpRing->tail = pI830->ring_next; \ + pI830->LpRing->space -= pI830->ring_used; \ + if (pI830->ring_next & 0x07) \ + FatalError("%s: ADVANCE_LP_RING: " \ + "ring_next (0x%x) isn't on a QWord boundary\n", \ + __FUNCTION__, pI830->ring_next); \ + OUTREG(LP_RING + RING_TAIL, pI830->ring_next); \ + pI830->ring_emitting = 0; \ +} while (0) + +/* + * XXX Note: the head/tail masks are different for 810 and i830. + * If the i810 always sets the higher bits to 0, then this shouldn't be + * a problem. Check this! + */ +#define DO_RING_IDLE() do { \ + int _head; \ + int _tail; \ + do { \ + _head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; \ + _tail = INREG(LP_RING + RING_TAIL) & I830_TAIL_MASK; \ + DELAY(10); \ + } while (_head != _tail); \ +} while (0) + +#define BEGIN_LP_RING(n) \ +do { \ + if (pI830->ring_emitting != 0) \ + FatalError("%s: BEGIN_LP_RING called without closing " \ + "ADVANCE_LP_RING\n", __FUNCTION__); \ + if ((n) > 2 && (I810_DEBUG&DEBUG_ALWAYS_SYNC)) \ + DO_RING_IDLE(); \ + pI830->ring_emitting = (n) * 4; \ + if ((n) & 1) \ + pI830->ring_emitting += 4; \ + if (pI830->LpRing->space < pI830->ring_emitting) \ + WaitRingFunc(pScrn, pI830->ring_emitting, 0); \ + pI830->ring_next = pI830->LpRing->tail; \ + if (I810_DEBUG & DEBUG_VERBOSE_RING) \ + ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME); \ + pI830->ring_used = 0; \ + if ((n) & 1) \ + OUT_RING(MI_NOOP); \ +} while (0) + +#endif /* _INTEL_RING_H */ |