summaryrefslogtreecommitdiff
path: root/bsd-core/drm_agpsupport.c
AgeCommit message (Collapse)Author
2005-08-05Rename the driver hooks in the DRM to something a little moreEric Anholt
understandable: preinit -> load postinit -> (removed) presetup -> firstopen postsetup -> (removed) open_helper -> open prerelease -> preclose free_filp_priv -> postclose pretakedown -> lastclose postcleanup -> unload release -> reclaim_buffers_locked version -> (removed) postinit and version were replaced with generic code in the Linux DRM (drivers now set their version numbers and description in the driver structure, like on BSD). postsetup wasn't used at all. Fixes the savage hooks for initializing and tearing down mappings at the right times. Testing involved at least starting X, running glxgears, killing glxgears, exiting X, and repeating. Tested on: FreeBSD (g200, g400, r200, r128) Linux (r200, savage4)
2005-07-20Add latest r300 support from r300.sf.net CVS. Patch submitted by volodya,Eric Anholt
with BSD fix from jkim and the r300_reg.h license from Nicolai Haehnle. Big thanks to everyone involved!
2005-06-29Get the BSD DRM compiling again after MGA and mapping changes. Note thatEric Anholt
i915 has been disabled for the moment, rather than working around linux-specific code in the shared dir.
2005-06-14Adds support for PCI cards to MGA DRMIan Romanick
This patch adds serveral new ioctls and a new query to get_param query to support PCI MGA cards. Two ioctls were added to implement interrupt based waiting. With this change, the client-side driver no longer needs to map the primary DMA region or the MMIO region. Previously, end-of-frame waiting was done by busy waiting in the client-side driver until one of the MMIO registers (the current DMA pointer) matched a pointer to the end of primary DMA space. By using interrupts, the busy waiting and the extra mappings are removed. A third ioctl was added to bootstrap DMA. This ioctl, which is used by the X-server, moves a *LOT* of code from the X-server into the kernel. This allows the kernel to do whatever needs to be done to setup DMA buffers. The entire process and the locations of the buffers are hidden from user-mode. Additionally, a get_param query was added to differentiate between G4x0 cards and G550 cards. A gap was left in the numbering sequence so that, if needed, G450 cards could be distinguished from G400 cards. According to Ville Syrjälä, the G4x0 cards and the G550 cards handle anisotropic filtering differently. This seems the most compatible way to let the client-side driver know which card it's own. Doing this very small change now eliminates the need to bump the DRM minor version twice. http://marc.theaimsgroup.com/?l=dri-devel&m=106625815319773&w=2 A number of ioctl handlers in linux-core were also modified so that they could be called in-kernel. In these cases, the in-kernel callable version kept the existing name (e.g., drm_agp_acquire) and the ioctl handler added _ioctl to the name (e.g., drm_agp_acquire_ioctl). This patch also replaces the drm_agp_do_release function with drm_agp_release. drm_agp_release (drm_core_agp_release in the previous patch) is very similar to drm_agp_do_release, and I saw no reason to have both. This commit *breaks the build* on BSD. Eric said that he would make the required updates to the BSD side soon. Xorg bug: 3259 Reviewed by: Eric Anholt
2005-05-27Modify drm_driver::device_is_agp to return a tri-state value to indicateIan Romanick
that a device absolutely is, absolutely is not, or may or may not be AGP. Modify the i915 DRM to use this to force all i9x5 devices to be "AGP" (even the PCI-e devices). Reported by: Lukas Hejtmanek
2005-05-16Added device_is_agp callback to drm_driver. This function is called by theIan Romanick
platform-specific drm_device_is_agp function. Added implementation of this function the the Linux-specific portion of the MGA driver to detect PCI G450 cards. Added code to the Linux-specific portion of the generic DRM layer to not initialize AGP infrastructure if the card is not AGP (this matches what already existed in BSD). Bumped the driver date and the driver patch-level for MGA. This mostly fixes bugzilla #3248. The BSD side still needs an implementation of mga_driver_device_is_agp.
2005-04-16Use /*- to begin license blocks in BSD code to reduce diffs against FreeBSDEric Anholt
CVS.
2005-01-17Add detection of whether the device is AGP by walking the capabilitiesEric Anholt
list.
2004-11-07Now that the memory debug code is gone, and all 3 BSDs have M_ZERO, stopEric Anholt
using drm_alloc/drm_free in the core and instead use plain malloc/free.
2004-11-06Commit first pieces of port to OpenBSD, done by Martin Lexa (martin atEric Anholt
martinlexa dot cz). Now that we've got porting for all three major BSDs (and the fourth being very similar to FreeBSD), move the mostly-duplication drm_os_* files into drmP.h. Remove some cruft from linux heritage and from pieces of the DRM that have since been removed. Note that things are still not quite working for even FreeBSD, but these are first steps at cleanup, and just a WIP checkpoint.
2004-11-06Commit WIP of BSD conversion to core model. Compiles for r128, radeon, butEric Anholt
doesn't run yet. Moves the ioctl definitions for these two drivers back to the shared code -- they aren't OS-specific.
2003-08-19- Remove $FreeBSD$ tags as they weren't too useful and merges are now beingEric Anholt
done through perforce. - Add copyright headers to drm_os_*bsd.h, still need to research the other copyright-less files better.
2003-04-26Remove #if 0'ed code.Eric Anholt
2003-03-11Merge back from FreeBSD-current, adding FreeBSD ID tags to aid futureEric Anholt
merging. Also includes an update to radeon PCI IDs.
2003-02-21Merge from bsd-4-0-0-branch.Eric Anholt
2002-09-26Fix one warning.Eric Anholt
2002-07-05merged bsd-3-0-0-branchAlan Hourihane
2002-01-27Import of XFree86 4.2.0David Dawes
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. * * Authors: * Keith Whitwell <keith@tungstengraphics.com> * Michel D�zer <michel@daenzer.net> */ #include "drmP.h" #include "drm.h" #include "radeon_drm.h" #include "radeon_drv.h" static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) { drm_radeon_private_t *dev_priv = dev->dev_private; if (state) dev_priv->irq_enable_reg |= mask; else dev_priv->irq_enable_reg &= ~mask; RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); } int radeon_enable_vblank(struct drm_device *dev, int crtc) { switch (crtc) { case 0: radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1); break; case 1: radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1); break; default: DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", crtc); return EINVAL; } return 0; } void radeon_disable_vblank(struct drm_device *dev, int crtc) { switch (crtc) { case 0: radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0); break; case 1: radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0); break; default: DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", crtc); break; } } static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv) { u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT); if (irqs) RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); return irqs; } /* Interrupts - Used for device synchronization and flushing in the * following circumstances: * * - Exclusive FB access with hw idle: * - Wait for GUI Idle (?) interrupt, then do normal flush. * * - Frame throttling, NV_fence: * - Drop marker irq's into command stream ahead of time. * - Wait on irq's with lock *not held* * - Check each for termination condition * * - Internally in cp_getbuffer, etc: * - as above, but wait with lock held??? * * NOTE: These functions are misleadingly named -- the irq's aren't * tied to dma at all, this is just a hangover from dri prehistory. */ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; u32 stat; /* Only consider the bits we're interested in - others could be used * outside the DRM */ stat = radeon_acknowledge_irqs(dev_priv); if (!stat) return IRQ_NONE; stat &= dev_priv->irq_enable_reg; /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) DRM_WAKEUP(&dev_priv->swi_queue); /* VBLANK interrupt */ if (stat & RADEON_CRTC_VBLANK_STAT) drm_handle_vblank(dev, 0); if (stat & RADEON_CRTC2_VBLANK_STAT) drm_handle_vblank(dev, 1); return IRQ_HANDLED; } static int radeon_emit_irq(struct drm_device * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; unsigned int ret; RING_LOCALS; atomic_inc(&dev_priv->swi_emitted); ret = atomic_read(&dev_priv->swi_emitted); BEGIN_RING(4); OUT_RING_REG(RADEON_LAST_SWI_REG, ret); OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); ADVANCE_RING(); COMMIT_RING(); return ret; } static int radeon_wait_irq(struct drm_device * dev, int swi_nr) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; int ret = 0; if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr) return 0; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ, RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); return ret; } u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) { drm_radeon_private_t *dev_priv = dev->dev_private; u32 crtc_cnt_reg, crtc_status_reg; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } if (crtc == 0) { crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME; crtc_status_reg = RADEON_CRTC_STATUS; } else if (crtc == 1) { crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME; crtc_status_reg = RADEON_CRTC2_STATUS; } else { return -EINVAL; } return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1); } /* Needs the lock as it touches the ring. */ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_irq_emit_t *emit = data; int result; LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } result = radeon_emit_irq(dev); if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; } /* Doesn't need the hardware lock. */ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_irq_wait_t *irqwait = data; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } return radeon_wait_irq(dev, irqwait->irq_seq); } /* drm_dma.h hooks */ void radeon_driver_irq_preinstall(struct drm_device * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; /* Disable *all* interrupts */ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); /* Clear bits if they're already high */ radeon_acknowledge_irqs(dev_priv); } int radeon_driver_irq_postinstall(struct drm_device * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; int ret; atomic_set(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); ret = drm_vblank_init(dev, 2); if (ret) return ret; dev->max_vblank_count = 0x001fffff; radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); return 0; } void radeon_driver_irq_uninstall(struct drm_device * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; if (!dev_priv) return; dev_priv->irq_enabled = 0; /* Disable *all* interrupts */ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); } int radeon_vblank_crtc_get(struct drm_device *dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; u32 flag; u32 value; flag = RADEON_READ(RADEON_GEN_INT_CNTL); value = 0; if (flag & RADEON_CRTC_VBLANK_MASK) value |= DRM_RADEON_VBLANK_CRTC1; if (flag & RADEON_CRTC2_VBLANK_MASK) value |= DRM_RADEON_VBLANK_CRTC2; return value; } int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value); return -EINVAL; } dev_priv->vblank_crtc = (unsigned int)value; return 0; }