summaryrefslogtreecommitdiff
path: root/linux-core/tdfx_drv.c
AgeCommit message (Collapse)Author
2002-07-05merged bsd-3-0-0-branchAlan Hourihane
2001-08-11new multihead code was missing Voodoo3 2000 and Voodoo4 support.Alan Hourihane
2001-08-08Update to the code I sent Linus and Alan this morning. Added some missingJeff Hartmann
agp chipsets to drm_agpsupport.h, redid the card detection common code to use a structure (avoids endian porting issues), changed the tdfx driver to use the kernel pci id '#defines'
2001-07-30Merge the multihead-1-0-0 branch into the trunk, with the exception of theDavid Dawes
glide header files. The changes include: - Brian Paul's changes to the tdfx client-side 3D driver to make it dlopen() the correct glide library (Voodoo3 or Voodoo5). This allows both types of the glide library to co-exist, and allows Voodoo3/Voodoo5 cards to be mixed in multi-head configs. - DRM kernel driver changes to allow a driver to set up multiple instances (minor numbers), one for each card present that the driver supports. This is currently implemented and tested only for the tdfx DRM driver. - Add some missing missing <stdarg.h> includes. - Some log message cleanups. - Change the 2D tdfx driver to access VGA legacy registers via their PCI I/O space access points rather than their legacy addresses, and fix some problems with the way the VGA-related bits are initialised. Status: - With these changes, multi-head direct rendering works with multiple Voodoo3 and/or Voodoo5 cards. This has been tested with two PCI Voodoo3 cards and an AGP Voodoo5 card, and all permutations of those. Caveats: - Xinerama is not supported. If Xinerama is enabled, then direct rendering gets disabled. - The text mode on secondary screens will show junk after the X server exits. - On some hardware, starting the X server on multiple 3dfx cards will result in a hard lockup. One workaround is to enable APIC support in a uni-processor kernel, or use an SMP kernel.
2001-07-23Fixes that allow the modules to be built into the kernelJeff Hartmann
2001-07-18Add module version name at a lower layer of the code, allows things to beJeff Hartmann
more flexible and allow older module versions to still work. Might not be final code if we move over to DRI kernel module version, but will be if we use XFree86 version. + Only build tdfx.o instead of tdfx-4_1_0.o since tdfx.o has never changed its API.
2001-07-16Added version string to the end of the kernel module name. This allowsJeff Hartmann
multiple versions of the kernel module to co-exist on one machine.
2001-03-07surround agp calls in drm_memory with __REALLY_HAVE_AGP instead ofAlan Hourihane
CONFIG_... remove include for agpsupport in tdfx_drv.c - not needed.
2001-02-16- Clean up the way customization of the templates is done.Gareth Hughes
- Fix old-style DMA for gamma driver (please test). - Pull out IRQ handling into drm_dma.h (please test on i810, gamma). - Lots of general cleanups, remove compiler warnings etc.
2001-02-15- Fix up merge.Gareth Hughes
- Update date stamps.
2001-02-15Merge mga-1-0-0-branch into trunk.Gareth Hughes
2001-01-08Merged tdfx-3-0-0Nathan Hand
2000-11-15Sync with Linux 2.4.0-test11-pre5 Provide backward compatibility testedRik Faith
against 2.2.18pre21 As usual, since all 2.4.0-test* kernels set LINUX_VERSION_CODE to the same value, if you are running a 2.4.0-test kernel, you MUST be running 2.4.0-test11-pre4 or later (although anything after 2.4.0-test11-pre1 should work fine -- I tested with pre4/pre5). I expect 2.2.x support to continue to work for all recent kernels, but I tested with 2.2.18pre21 -- we use the old intermodule symbol communication for 2.2.x kernels, so they should all continue to work.
2000-09-29Audit calls to schedule() Remove tags from files shared with Linux kernelRik Faith
tree Remove debugging statements to make debugging more useful Other minor cleanups in preparation for sync with Linux 2.4.0-test9-pre7
2000-09-27Merged the mga-lock-debug-0-2-0-branch with the trunk. This includesJeff Hartmann
several fixes including: (Jeff) Really disable multitexture (Broken since Mesa 3.4 integration.) (Jeff) Various changes in mga_state.c in the kernel module, which includes a fix to the bug where the first OGL application hangs the machine w/out rendering anything. This also includes defines for the warp registers so they are easily human readable. (Rik and Jeff) Fixed all the schedule loops in the kernel to look like they are supposed too. (Jeff) Configurable agp modes: Add the option "AGPMode2x" or "AGPMode4x" to your XF86Config file. (Rik) Various cleanups to the mga kernel driver to make it easier to read and debug. (Rik) Removed alot of DRM_DEBUG statements from the kernel driver.
2000-09-24commit xfree86 4.0.1d-pre updateAlan Hourihane
2000-09-10Sync with 2.4.0-test8 kernel.Gareth Hughes
2000-09-06Sync with 2.4.0-test8-pre5 kernel.Gareth Hughes
2000-08-26Sync with Linux 2.4.0-test7 Add signal blocking support to all driversRik Faith
(using control-z on a running direct-rendering client should work now)
2000-08-08Sync with Linux 2.4.0-test6-pre8Rik Faith
2000-08-04Sync with Linux 2.4.0-test6-pre2Rik Faith
2000-07-21Revert some changes and try alternative way to clean up AGP handling.Rik Faith
2000-07-21Changes to make AGP optional for in-kernel buildsRik Faith
2000-07-20More fixups for kernel build: EXPORT_SYMTAB warning removalRik Faith
put_module_symbol clean up of tdfx tdfx_cleanup routine Makefile.kernel fix
2000-07-20Fix signature for *_options functionRik Faith
2000-07-20Added support for building as modules or as part of monolithic kernelRik Faith
2000-07-19Bump driver dates and add descriptionsRik Faith
2000-07-19Sync with Linux 2.4.0-test4 kernelRik Faith
2000-06-13Unify code with kernel: Change some spacing in comments Add #includeRik Faith
<linux/config.h> to all *_drv.c files
2000-06-08Merged glxmisc-3-0-0Brian Paul
2000-04-04Merged mga branch with trunkJeff Hartmann
2000-03-16Merge with 4.0Jeff Hartmann
2000-02-223.9.18 mergeKevin E Martin
2000-01-12Add a drm_poll function to the tdfx driver. This fixes the problem withDaryll Strauss
3.9.17 where the server hangs when the mouse is first moved.
2000-01-06Import of XFree86 3.9.17Rik Faith
1999-12-05First DRI release of 3dfx driver.Daryll Strauss
he * 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 NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS 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. */ /* * ChangeLog: * 2001-11-16 Torsten Duwe <duwe@caldera.de> * added context constructor/destructor hooks, * needed by SiS driver's memory management. */ #include "drmP.h" /******************************************************************/ /** \name Context bitmap support */ /*@{*/ /** * Free a handle from the context bitmap. * * \param dev DRM device. * \param ctx_handle context handle. * * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry * in drm_device::ctx_idr, while holding the drm_device::struct_mutex * lock. */ void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle) { mutex_lock(&dev->struct_mutex); idr_remove(&dev->ctx_idr, ctx_handle); mutex_unlock(&dev->struct_mutex); } /** * Context bitmap allocation. * * \param dev DRM device. * \return (non-negative) context handle on success or a negative number on failure. * * Allocate a new idr from drm_device::ctx_idr while holding the * drm_device::struct_mutex lock. */ static int drm_ctxbitmap_next(struct drm_device *dev) { int new_id; int ret; again: if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) { DRM_ERROR("Out of memory expanding drawable idr\n"); return -ENOMEM; } mutex_lock(&dev->struct_mutex); ret = idr_get_new_above(&dev->ctx_idr, NULL, DRM_RESERVED_CONTEXTS, &new_id); if (ret == -EAGAIN) { mutex_unlock(&dev->struct_mutex); goto again; } mutex_unlock(&dev->struct_mutex); return new_id; } /** * Context bitmap initialization. * * \param dev DRM device. * * Initialise the drm_device::ctx_idr */ int drm_ctxbitmap_init(struct drm_device *dev) { idr_init(&dev->ctx_idr); return 0; } /** * Context bitmap cleanup. * * \param dev DRM device. * * Free all idr members using drm_ctx_sarea_free helper function * while holding the drm_device::struct_mutex lock. */ void drm_ctxbitmap_cleanup(struct drm_device *dev) { mutex_lock(&dev->struct_mutex); idr_remove_all(&dev->ctx_idr); mutex_unlock(&dev->struct_mutex); } /*@}*/ /******************************************************************/ /** \name Per Context SAREA Support */ /*@{*/ /** * Get per-context SAREA. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx_priv_map structure. * \return zero on success or a negative number on failure. * * Gets the map from drm_device::ctx_idr with the handle specified and * returns its handle. */ int drm_getsareactx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx_priv_map *request = data; struct drm_map *map; struct drm_map_list *_entry; mutex_lock(&dev->struct_mutex); map = idr_find(&dev->ctx_idr, request->ctx_id); if (!map) { mutex_unlock(&dev->struct_mutex); return -EINVAL; } mutex_unlock(&dev->struct_mutex); request->handle = NULL; list_for_each_entry(_entry, &dev->maplist, head) { if (_entry->map == map) { request->handle = (void *)(unsigned long)_entry->user_token; break; } } if (request->handle == NULL) return -EINVAL; return 0; } /** * Set per-context SAREA. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx_priv_map structure. * \return zero on success or a negative number on failure. * * Searches the mapping specified in \p arg and update the entry in * drm_device::ctx_idr with it. */ int drm_setsareactx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx_priv_map *request = data; struct drm_map *map = NULL; struct drm_map_list *r_list = NULL; mutex_lock(&dev->struct_mutex); list_for_each_entry(r_list, &dev->maplist, head) { if (r_list->map && r_list->user_token == (unsigned long) request->handle) goto found; } bad: mutex_unlock(&dev->struct_mutex); return -EINVAL; found: map = r_list->map; if (!map) goto bad; if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id))) goto bad; mutex_unlock(&dev->struct_mutex); return 0; } /*@}*/ /******************************************************************/ /** \name The actual DRM context handling routines */ /*@{*/ /** * Switch context. * * \param dev DRM device. * \param old old context handle. * \param new new context handle. * \return zero on success or a negative number on failure. * * Attempt to set drm_device::context_flag. */ static int drm_context_switch(struct drm_device *dev, int old, int new) { if (test_and_set_bit(0, &dev->context_flag)) { DRM_ERROR("Reentering -- FIXME\n"); return -EBUSY; } DRM_DEBUG("Context switch from %d to %d\n", old, new); if (new == dev->last_context) { clear_bit(0, &dev->context_flag); return 0; } return 0; } /** * Complete context switch. * * \param dev DRM device. * \param new new context handle. * \return zero on success or a negative number on failure. * * Updates drm_device::last_context and drm_device::last_switch. Verifies the * hardware lock is held, clears the drm_device::context_flag and wakes up * drm_device::context_wait. */ static int drm_context_switch_complete(struct drm_device *dev, int new) { dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ dev->last_switch = jiffies; if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("Lock isn't held after context switch\n"); } /* If a context switch is ever initiated when the kernel holds the lock, release that lock here. */ clear_bit(0, &dev->context_flag); wake_up(&dev->context_wait); return 0; } /** * Reserve contexts. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx_res structure. * \return zero on success or a negative number on failure. */ int drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx_res *res = data; struct drm_ctx ctx; int i; 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], &ctx, sizeof(ctx))) return -EFAULT; } } res->count = DRM_RESERVED_CONTEXTS; return 0; } /** * Add context. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Get a new handle for the context and copy to userspace. */ int drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx_list *ctx_entry; struct drm_ctx *ctx = data; ctx->handle = drm_ctxbitmap_next(dev); if (ctx->handle == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ ctx->handle = drm_ctxbitmap_next(dev); } DRM_DEBUG("%d\n", ctx->handle); if (ctx->handle == -1) { DRM_DEBUG("Not enough free contexts.\n"); /* Should this return -EBUSY instead? */ return -ENOMEM; } if (ctx->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_ctor) if (!dev->driver->context_ctor(dev, ctx->handle)) { DRM_DEBUG("Running out of ctxs or memory.\n"); return -ENOMEM; } } ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST); if (!ctx_entry) { DRM_DEBUG("out of memory\n"); return -ENOMEM; } INIT_LIST_HEAD(&ctx_entry->head); ctx_entry->handle = ctx->handle; ctx_entry->tag = file_priv; mutex_lock(&dev->ctxlist_mutex); list_add(&ctx_entry->head, &dev->ctxlist); ++dev->ctx_count; mutex_unlock(&dev->ctxlist_mutex); return 0; } int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { /* This does nothing */ return 0; } /** * Get context. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. */ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx *ctx = data; /* This is 0, because we don't handle any context flags */ ctx->flags = 0; return 0; } /** * Switch context. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Calls context_switch(). */ int drm_switchctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx *ctx = data; DRM_DEBUG("%d\n", ctx->handle); return drm_context_switch(dev, dev->last_context, ctx->handle); } /** * New context. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Calls context_switch_complete(). */ int drm_newctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx *ctx = data; DRM_DEBUG("%d\n", ctx->handle); drm_context_switch_complete(dev, ctx->handle); return 0; } /** * Remove context. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * If not the special kernel context, calls ctxbitmap_free() to free the specified context. */ int drm_rmctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx *ctx = data; DRM_DEBUG("%d\n", ctx->handle); if (ctx->handle == DRM_KERNEL_CONTEXT + 1) { file_priv->remove_auth_on_close = 1; } if (ctx->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_dtor) dev->driver->context_dtor(dev, ctx->handle); drm_ctxbitmap_free(dev, ctx->handle); } mutex_lock(&dev->ctxlist_mutex); if (!list_empty(&dev->ctxlist)) { struct drm_ctx_list *pos, *n; list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { if (pos->handle == ctx->handle) { list_del(&pos->head); drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST); --dev->ctx_count; } } } mutex_unlock(&dev->ctxlist_mutex); return 0; } /*@}*/