summaryrefslogtreecommitdiff
path: root/shared-core
AgeCommit message (Collapse)Author
2008-06-05modesetting: initial attempt at debonging fbDave Airlie
2008-06-04drm: introduce generation counter to interface.Dave Airlie
Idea being if you want to add new crtc/output/encoder dynamically later, you just increase the generation counter and userspace should re-read all the resources
2008-06-03drm: sg alloc should write back the handle to userspaceDave Airlie
2008-06-02drm: add functions to get/set gamma rampsDave Airlie
2008-06-02drm/modesetting: another re-org of some internals.Dave Airlie
Move dpms into the helper functions. Move crtc into the encoder. Move disable unused functions into the helper.
2008-05-30RADEON: fix typo in last commitAlex Deucher
2008-05-30Merge commit 'origin/master' into drm-gemEric Anholt
Conflicts: linux-core/Makefile.kernel shared-core/i915_drv.h shared-core/nouveau_state.c
2008-05-30r500: attempt to make AGP work by programming agp base in the MC correctlyDave Airlie
2008-05-30drm: switch possible crtc/clones over to encodersDave Airlie
2008-05-30modesetting: the great renaming.Dave Airlie
Okay we have crtc, encoder and connectors. No more outputs exposed beyond driver internals I've broken intel tv connector stuff. Really for TV we should have one TV connector, with a sub property for the type of signal been driven over it
2008-05-30drm: attach an encoder.Dave Airlie
Time to do some renaming on the connectors I think
2008-05-30drm: add more encoder interfacesDave Airlie
2008-05-30modesetting: reorganise out crtc/outputs are allocated.Dave Airlie
Use subclassing from the drivers to allocate the objects. This saves two objects being allocated for each crtc/output and generally makes exit paths cleaner.
2008-05-29modesetting: reorganise code into core and helper functions.Dave Airlie
This splits a lot of the core modesetting code out into a file of helper functions, that are only called from themselves and/or the driver. The driver gets called into more often or can call these functions from itself if it is a helper using driver. I've broken framebuffer resize doing this but I didn't like the API for that in any case.
2008-05-28Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into ↵Alan Hourihane
modesetting-101 Conflicts: shared-core/i915_dma.c shared-core/i915_drv.h
2008-05-28radeon: split microcode out into a separate header file.Dave Airlie
2008-05-27[intel-gem] Replace idlelock usage with real lock acquisition.Eric Anholt
2008-05-28i915: fix BSD bh, DRI2 not uses anywhere elseDave Airlie
2008-05-28radeon: bump release date/version for r500 3D supportDave Airlie
2008-05-27RADEON: add get_param for number of GB pipesAlex Deucher
2008-05-27[i915] Fix typo in (unused) START_ADDR definition.Jie Luo
2008-05-27[FreeBSD] Add vblank-rework support and get drivers building.Robert Noland
The i915 driver now works again.
2008-05-26[i915] leave interrupts masked off when not in use.Keith Packard
The interrupt enable register cannot be used to temporarily disable interrupts, instead use the interrupt mask register. Note that this change means that a pile of buffers will be left stuck on the chip as the final interrupts will not be recognized to come and drain things.
2008-05-25[intel-gem] Add DRM_I915_GEM_BUSY ioctl to check for idle buffers.Keith Packard
This new ioctl returns whether re-using the buffer would force a wait.
2008-05-23i915: do a better job of parsing VBIOS dataJesse Barnes
Add code to get panel modes from the VBIOS if present and check whether certain outputs exist. Should make our display detection code a little more robust.
2008-05-22[intel] Add debug code to verify the cached ring tail pointer.Keith Packard
Recording the tail pointer in a local variable improves performance, but if someone messes up and fails to reload at the right time, the driver will write commands to the wrong part of the ring and scramble execution badly. This change (available by setting I915_RING_VALIDATE to 1) checks to make sure the cached tail pointer matches the hardware tail pointer at each ring buffer addition, calling BUG_ON when that's not true.
2008-05-22[gem] Release GEM buffers from work task scheduled from IRQ.Eric Anholt
There are now 3 lists. Active is buffers currently in the ringbuffer. Flushing is not in the ringbuffer, but needs a flush before unbinding. Inactive is as before. This prevents object_free → unbind → wait_rendering → object_reference and a kernel oops about weird refcounting. This also avoids an synchronous extra flush and wait when freeing a buffer which had a write_domain set (such as a temporary rendered to and then from using the 2d engine). It will sit around on the flushing list until the appropriate flush gets emitted, or we need the GTT space for another operation.
2008-05-23r500: add two more register ranges for mesa driver to setupDave Airlie
2008-05-23drm: fix nouveau warningDave Airlie
2008-05-22i915: init bo mm at driver init only when modeset=1Hong Liu
To avoid bo memory manager being inited twice, it will be called at firstopen when modeset is not enabled.
2008-05-21[gem] Replace ring throttling hack with actual time measurement.Eric Anholt
2008-05-21rs690/r500: vblank support.Dave Airlie
The new display controller has the vblank interrupts in a different place. Add support for vbl interrupts for these chips
2008-05-20[gem] Use a separate sequence number field from classic/ttmEric Anholt
This lets us get some qualities we desire, such as using the full 32-bit range (except zero), avoiding DRM_WAIT_ON, and a 1:1 mapping of active sequence numbers to request structs, which will be used soon for throttling and interrupt-driven list cleanup.
2008-05-20[gem] Rename sequence numbers from "cookie" to "seqno"Eric Anholt
2008-05-20[gem] Clean up active/inactive list handling using helper functions.Eric Anholt
Additionally, a boolean active field is added to indicate which list an object is on, rather than smashing last_rendering_cookie to 0 to show inactive. This will help with flush-reduction later on, and makes the code clearer.
2008-05-17r500: add more register ranges for Mesa driverDave Airlie
2008-05-15[gem] Hold dev->struct_mutex to protect structure data.Eric Anholt
2008-05-15[gem] Rename the GTT LRU lists to active (executing) and inactive (idle).Eric Anholt
2008-05-13RS4xx: separate out RS400 and RS480 IGP chipsAlex Deucher
RS400 (intel based IGP) and RS480 (AMD based IGP) have different MC and GART setups. Currently we only support RS480.
2008-05-13Merge branch 'modesetting-101' of ssh://git.freedesktop.org/git/mesa/drm ↵Jesse Barnes
into modesetting-101
2008-05-13i915: register definition & header file cleanupJesse Barnes
It would be nice if one day the DRM driver was the canonical source for register definitions and core macros. To that end, this patch cleans things up quite a bit, removing redundant definitions (some with different names referring to the same register) and generally tidying up the header file.
2008-05-13i915: execbuf now works without i915_dma_init being calledJakob Bornecrantz
2008-05-12i915: TV hotplug fixesJesse Barnes
In order to avoid recursive ->detect->interrupt->detect->interrupt->... we need to disable TV hotplug interrupts in intel_tv.c:intel_tv_detect_type. We also need to enable the TV interrupt detection and hotplug sequence properly in i915_irq.c.
2008-05-12[GEM] Typo (and thinking) fixes in drm-gem.txt and doxygen.Eric Anholt
2008-05-12[intel] When polling for ring space, sleep for a lot longer (10ms)Keith Packard
If the ring is full, the engine will surely be running for more than 10ms.
2008-05-12fix kernel oops when removing fbHong Liu
drm_crtc->fb may point to NULL, f.e X server will allocate a new fb and assign it to the CRTC at startup, when X server exits, it will destroy the allocated fb, making drm_crtc->fb points to NULL.
2008-05-12modeset init code cleanupHong Liu
moving modeset init code into one function and correct error handling druing i915 init
2008-05-12fix G33 hardware status page in modesetHong Liu
We need to alloc a hw status page bo for G33 if modeset is enabled since the 2D driver can't alloc gfx memory when working in drm modeset.
2008-05-12RADEON: fix copy/pasto in last commitAlex Deucher
2008-05-12R3/4/5: init pipe setup in drmAlex Deucher
Similar (broken) code in mesa needs to be removed
l opt">; int i; ctx = fpriv->hw_state[idx - 1]; if (idx == 0 || ctx == NULL) return; if (ctx->is_2d_only) { /* 2D applications only care about certain pieces * of state. */ ctx->drawop = upa_readl(&ffb->drawop); ctx->ppc = upa_readl(&ffb->ppc); ctx->wid = upa_readl(&ffb->wid); ctx->fg = upa_readl(&ffb->fg); ctx->bg = upa_readl(&ffb->bg); ctx->xclip = upa_readl(&ffb->xclip); ctx->fbc = upa_readl(&ffb->fbc); ctx->rop = upa_readl(&ffb->rop); ctx->cmp = upa_readl(&ffb->cmp); ctx->matchab = upa_readl(&ffb->matchab); ctx->magnab = upa_readl(&ffb->magnab); ctx->pmask = upa_readl(&ffb->pmask); ctx->xpmask = upa_readl(&ffb->xpmask); ctx->lpat = upa_readl(&ffb->lpat); ctx->fontxy = upa_readl(&ffb->fontxy); ctx->fontw = upa_readl(&ffb->fontw); ctx->fontinc = upa_readl(&ffb->fontinc); /* stencil/stencilctl only exists on FFB2+ and later * due to the introduction of 3DRAM-III. */ if (fpriv->ffb_type == ffb2_vertical_plus || fpriv->ffb_type == ffb2_horizontal_plus) { ctx->stencil = upa_readl(&ffb->stencil); ctx->stencilctl = upa_readl(&ffb->stencilctl); } for (i = 0; i < 32; i++) ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]); ctx->ucsr = upa_readl(&ffb->ucsr); return; } /* Fetch drawop. */ ctx->drawop = upa_readl(&ffb->drawop); /* If we were saving the vertex registers, this is where * we would do it. We would save 32 32-bit words starting * at ffb->suvtx. */ /* Capture rendering attributes. */ ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */ ctx->wid = upa_readl(&ffb->wid); /* Current WID */ ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */ ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */ ctx->consty = upa_readl(&ffb->consty); /* Constant Y */ ctx->constz = upa_readl(&ffb->constz); /* Constant Z */ ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */ ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */ ctx->vclipmin = upa_readl(&ffb->vclipmin); /* Primary XY clip, minimum */ ctx->vclipmax = upa_readl(&ffb->vclipmax); /* Primary XY clip, maximum */ ctx->vclipzmin = upa_readl(&ffb->vclipzmin); /* Primary Z clip, minimum */ ctx->vclipzmax = upa_readl(&ffb->vclipzmax); /* Primary Z clip, maximum */ ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */ ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */ ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */ ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */ ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */ ctx->blendc1 = upa_readl(&ffb->blendc1); /* Alpha Blend Color 1 */ ctx->blendc2 = upa_readl(&ffb->blendc2); /* Alpha Blend Color 2 */ ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */ ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */ ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */ ctx->matchab = upa_readl(&ffb->matchab); /* Buffer A/B Match Ops */ ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */ ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */ ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */ ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */ ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */ ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */ ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */ /* Auxiliary Clips. */ ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min); ctx->auxclip0max = upa_readl(&ffb->auxclip[0].max); ctx->auxclip1min = upa_readl(&ffb->auxclip[1].min); ctx->auxclip1max = upa_readl(&ffb->auxclip[1].max); ctx->auxclip2min = upa_readl(&ffb->auxclip[2].min); ctx->auxclip2max = upa_readl(&ffb->auxclip[2].max); ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min); ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max); ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */ ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */ ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */ ctx->fontinc = upa_readl(&ffb->fontinc); /* Font X/Y Increment */ /* These registers/features only exist on FFB2 and later chips. */ if (fpriv->ffb_type >= ffb2_prototype) { ctx->dcss1 = upa_readl(&ffb->dcss1); /* Depth Cue Scale Slope 1 */ ctx->dcss2 = upa_readl(&ffb->dcss2); /* Depth Cue Scale Slope 2 */ ctx->dcss2 = upa_readl(&ffb->dcss3); /* Depth Cue Scale Slope 3 */ ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */ ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */ ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */ ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */ ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */ ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */ /* And stencil/stencilctl only exists on FFB2+ and later * due to the introduction of 3DRAM-III. */ if (fpriv->ffb_type == ffb2_vertical_plus || fpriv->ffb_type == ffb2_horizontal_plus) { ctx->stencil = upa_readl(&ffb->stencil); ctx->stencilctl = upa_readl(&ffb->stencilctl); } } /* Save the 32x32 area pattern. */ for (i = 0; i < 32; i++) ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]); /* Finally, stash away the User Constol/Status Register. */ ctx->ucsr = upa_readl(&ffb->ucsr); } static void ffb_restore_context(ffb_dev_priv_t * fpriv, int old, int idx) { ffb_fbcPtr ffb = fpriv->regs; struct ffb_hw_context *ctx; int i; ctx = fpriv->hw_state[idx - 1]; if (idx == 0 || ctx == NULL) return; if (ctx->is_2d_only) { /* 2D applications only care about certain pieces * of state. */ upa_writel(ctx->drawop, &ffb->drawop); /* If we were restoring the vertex registers, this is where * we would do it. We would restore 32 32-bit words starting * at ffb->suvtx. */ upa_writel(ctx->ppc, &ffb->ppc); upa_writel(ctx->wid, &ffb->wid); upa_writel(ctx->fg, &ffb->fg); upa_writel(ctx->bg, &ffb->bg); upa_writel(ctx->xclip, &ffb->xclip); upa_writel(ctx->fbc, &ffb->fbc); upa_writel(ctx->rop, &ffb->rop); upa_writel(ctx->cmp, &ffb->cmp); upa_writel(ctx->matchab, &ffb->matchab); upa_writel(ctx->magnab, &ffb->magnab); upa_writel(ctx->pmask, &ffb->pmask); upa_writel(ctx->xpmask, &ffb->xpmask); upa_writel(ctx->lpat, &ffb->lpat); upa_writel(ctx->fontxy, &ffb->fontxy); upa_writel(ctx->fontw, &ffb->fontw); upa_writel(ctx->fontinc, &ffb->fontinc); /* stencil/stencilctl only exists on FFB2+ and later * due to the introduction of 3DRAM-III. */ if (fpriv->ffb_type == ffb2_vertical_plus || fpriv->ffb_type == ffb2_horizontal_plus) { upa_writel(ctx->stencil, &ffb->stencil); upa_writel(ctx->stencilctl, &ffb->stencilctl); upa_writel(0x80000000, &ffb->fbc); upa_writel((ctx->stencilctl | 0x80000), &ffb->rawstencilctl); upa_writel(ctx->fbc, &ffb->fbc); } for (i = 0; i < 32; i++) upa_writel(ctx->area_pattern[i], &ffb->pattern[i]); upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr); return; } /* Restore drawop. */ upa_writel(ctx->drawop, &ffb->drawop); /* If we were restoring the vertex registers, this is where * we would do it. We would restore 32 32-bit words starting * at ffb->suvtx. */ /* Restore rendering attributes. */ upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */ upa_writel(ctx->wid, &ffb->wid); /* Current WID */ upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */ upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */ upa_writel(ctx->consty, &ffb->consty); /* Constant Y */ upa_writel(ctx->constz, &ffb->constz); /* Constant Z */ upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */ upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */ upa_writel(ctx->vclipmin, &ffb->vclipmin); /* Primary XY clip, minimum */ upa_writel(ctx->vclipmax, &ffb->vclipmax); /* Primary XY clip, maximum */ upa_writel(ctx->vclipzmin, &ffb->vclipzmin); /* Primary Z clip, minimum */ upa_writel(ctx->vclipzmax, &ffb->vclipzmax); /* Primary Z clip, maximum */ upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */ upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */ upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */ upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */ upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */ upa_writel(ctx->blendc1, &ffb->blendc1); /* Alpha Blend Color 1 */ upa_writel(ctx->blendc2, &ffb->blendc2); /* Alpha Blend Color 2 */ upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */ upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */ upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */ upa_writel(ctx->matchab, &ffb->matchab); /* Buffer A/B Match Ops */ upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */ upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */ upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */ upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */ upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */ upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */ upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */ /* Auxiliary Clips. */ upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min); upa_writel(ctx->auxclip0max, &ffb->auxclip[0].max); upa_writel(ctx->auxclip1min, &ffb->auxclip[1].min); upa_writel(ctx->auxclip1max, &ffb->auxclip[1].max); upa_writel(ctx->auxclip2min, &ffb->auxclip[2].min); upa_writel(ctx->auxclip2max, &ffb->auxclip[2].max); upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min); upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max); upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */ upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */ upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */ upa_writel(ctx->fontinc, &ffb->fontinc); /* Font X/Y Increment */ /* These registers/features only exist on FFB2 and later chips. */ if (fpriv->ffb_type >= ffb2_prototype) { upa_writel(ctx->dcss1, &ffb->dcss1); /* Depth Cue Scale Slope 1 */ upa_writel(ctx->dcss2, &ffb->dcss2); /* Depth Cue Scale Slope 2 */ upa_writel(ctx->dcss3, &ffb->dcss2); /* Depth Cue Scale Slope 3 */ upa_writel(ctx->dcs2, &ffb->dcs2); /* Depth Cue Scale 2 */ upa_writel(ctx->dcs3, &ffb->dcs3); /* Depth Cue Scale 3 */ upa_writel(ctx->dcs4, &ffb->dcs4); /* Depth Cue Scale 4 */ upa_writel(ctx->dcd2, &ffb->dcd2); /* Depth Cue Depth 2 */ upa_writel(ctx->dcd3, &ffb->dcd3); /* Depth Cue Depth 3 */ upa_writel(ctx->dcd4, &ffb->dcd4); /* Depth Cue Depth 4 */ /* And stencil/stencilctl only exists on FFB2+ and later * due to the introduction of 3DRAM-III. */ if (fpriv->ffb_type == ffb2_vertical_plus || fpriv->ffb_type == ffb2_horizontal_plus) { /* Unfortunately, there is a hardware bug on * the FFB2+ chips which prevents a normal write * to the stencil control register from working * as it should. * * The state controlled by the FFB stencilctl register * really gets transferred to the per-buffer instances * of the stencilctl register in the 3DRAM chips. * * The bug is that FFB does not update buffer C correctly, * so we have to do it by hand for them. */ /* This will update buffers A and B. */ upa_writel(ctx->stencil, &ffb->stencil); upa_writel(ctx->stencilctl, &ffb->stencilctl); /* Force FFB to use buffer C 3dram regs. */ upa_writel(0x80000000, &ffb->fbc); upa_writel((ctx->stencilctl | 0x80000), &ffb->rawstencilctl); /* Now restore the correct FBC controls. */ upa_writel(ctx->fbc, &ffb->fbc); } } /* Restore the 32x32 area pattern. */ for (i = 0; i < 32; i++) upa_writel(ctx->area_pattern[i], &ffb->pattern[i]); /* Finally, stash away the User Constol/Status Register. * The only state we really preserve here is the picking * control. */ upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr); } #define FFB_UCSR_FB_BUSY 0x01000000 #define FFB_UCSR_RP_BUSY 0x02000000 #define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY) static void FFBWait(ffb_fbcPtr ffb) { int limit = 100000; do { u32 regval = upa_readl(&ffb->ucsr); if ((regval & FFB_UCSR_ALL_BUSY) == 0) break; } while (--limit); } int ffb_context_switch(struct drm_device * dev, int old, int new) { ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; #if DRM_DMA_HISTOGRAM dev->ctx_start = get_cycles(); #endif DRM_DEBUG("Context switch from %d to %d\n", old, new); if (new == dev->last_context || dev->last_context == 0) { dev->last_context = new; return 0; } FFBWait(fpriv->regs); ffb_save_context(fpriv, old); ffb_restore_context(fpriv, old, new); FFBWait(fpriv->regs); dev->last_context = new; return 0; } int ffb_resctx(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { drm_ctx_res_t res; drm_ctx_t ctx; int i; DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); if (copy_from_user(&res, (drm_ctx_res_t __user *) arg, sizeof(res))) return -EFAULT; if (res.count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; if (copy_to_user(&res.contexts[i], &i, sizeof(i))) return -EFAULT; } } res.count = DRM_RESERVED_CONTEXTS; if (copy_to_user((drm_ctx_res_t __user *) arg, &res, sizeof(res))) return -EFAULT; return 0; } int ffb_addctx(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; struct drm_device *dev = priv->dev; drm_ctx_t ctx; int idx; if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) return -EFAULT; idx = ffb_alloc_queue(dev, (ctx.flags & _DRM_CONTEXT_2DONLY)); if (idx < 0) return -ENFILE; DRM_DEBUG("%d\n", ctx.handle); ctx.handle = idx; if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx))) return -EFAULT; return 0; } int ffb_modctx(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; struct drm_device *dev = priv->dev; ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; struct ffb_hw_context *hwctx; drm_ctx_t ctx; int idx; if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) return -EFAULT; idx = ctx.handle; if (idx <= 0 || idx >= FFB_MAX_CTXS) return -EINVAL; hwctx = fpriv->hw_state[idx - 1]; if (hwctx == NULL) return -EINVAL; if ((ctx.flags & _DRM_CONTEXT_2DONLY) == 0) hwctx->is_2d_only = 0; else hwctx->is_2d_only = 1; return 0; } int ffb_getctx(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; struct drm_device *dev = priv->dev; ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; struct ffb_hw_context *hwctx; drm_ctx_t ctx; int idx; if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) return -EFAULT; idx = ctx.handle; if (idx <= 0 || idx >= FFB_MAX_CTXS) return -EINVAL; hwctx = fpriv->hw_state[idx - 1]; if (hwctx == NULL) return -EINVAL; if (hwctx->is_2d_only != 0) ctx.flags = _DRM_CONTEXT_2DONLY; else ctx.flags = 0; if (copy_to_user((drm_ctx_t __user *) arg, &ctx, sizeof(ctx))) return -EFAULT; return 0; } int ffb_switchctx(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; struct drm_device *dev = priv->dev; drm_ctx_t ctx; if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return ffb_context_switch(dev, dev->last_context, ctx.handle); } int ffb_newctx(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { drm_ctx_t ctx; if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); return 0; } int ffb_rmctx(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg) { drm_ctx_t ctx; drm_file_t *priv = filp->private_data; struct drm_device *dev = priv->dev; ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; int idx; if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx))) return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); idx = ctx.handle - 1; if (idx < 0 || idx >= FFB_MAX_CTXS) return -EINVAL; if (fpriv->hw_state[idx] != NULL) { kfree(fpriv->hw_state[idx]); fpriv->hw_state[idx] = NULL; } return 0; } static void ffb_driver_reclaim_buffers_locked(struct drm_device * dev) { ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock); int idx; idx = context - 1; if (fpriv && context != DRM_KERNEL_CONTEXT && fpriv->hw_state[idx] != NULL) { kfree(fpriv->hw_state[idx]); fpriv->hw_state[idx] = NULL; } } static void ffb_driver_lastclose(struct drm_device * dev) { if (dev->dev_private) kfree(dev->dev_private); } static void ffb_driver_unload(struct drm_device * dev) { if (ffb_position != NULL) kfree(ffb_position); } static int ffb_driver_kernel_context_switch_unlock(struct drm_device *dev) { dev->lock.filp = 0; { __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock; unsigned int old, new, prev, ctx; ctx = lock.context; do { old = *plock; new = ctx; prev = cmpxchg(plock, old, new); } while (prev != old); } wake_up_interruptible(&dev->lock.lock_queue); } unsigned long ffb_driver_get_map_ofs(drm_map_t * map) { return (map->offset & 0xffffffff); } unsigned long ffb_driver_get_reg_ofs(struct drm_device * dev) { ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private; if (ffb_priv) return ffb_priv->card_phys_base; return 0; }