http://drm.bkbits.net/drm-2.6
airlied@pdx.freedesktop.org|ChangeSet|20040410135643|23869 airlied

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/04/12 20:53:29-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-drm
# 
# drivers/char/drm/i830_irq.c
#   2004/04/12 20:53:26-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i830_dma.c
#   2004/04/12 20:53:26-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i810_dma.c
#   2004/04/12 20:53:26-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/10 06:56:43-07:00 airlied@pdx.freedesktop.org 
#   From Jon Smirl:
#   This code allows the mesa drivers to use a single definition of the DRM sarea/IOCTLS 
# 
# drivers/char/drm/radeon_drm.h
#   2004/04/10 06:56:33-07:00 airlied@pdx.freedesktop.org +60 -27
#   From Jon Smirl:
#   This code allows the mesa drivers to use a single definition of the DRM sarea/IOCTLS 
# 
# drivers/char/drm/r128_drm.h
#   2004/04/10 06:56:33-07:00 airlied@pdx.freedesktop.org +42 -19
#   From Jon Smirl:
#   This code allows the mesa drivers to use a single definition of the DRM sarea/IOCTLS 
# 
# drivers/char/drm/mga_drm.h
#   2004/04/10 06:56:33-07:00 airlied@pdx.freedesktop.org +24 -11
#   From Jon Smirl:
#   This code allows the mesa drivers to use a single definition of the DRM sarea/IOCTLS 
# 
# drivers/char/drm/drm_sarea.h
#   2004/04/10 06:56:33-07:00 airlied@pdx.freedesktop.org +14 -0
#   From Jon Smirl:
#   This code allows the mesa drivers to use a single definition of the DRM sarea/IOCTLS 
# 
# ChangeSet
#   2004/04/10 06:27:26-07:00 airlied@pdx.freedesktop.org 
#   * Introduce COMMIT_RING() as in radeon DRM, stop using error prone
#     writeback for ring read pointer (Paul Mackerras)
#   * Get rid of some superfluous stuff, minor fixes
# 
# drivers/char/drm/r128_state.c
#   2004/04/10 06:27:19-07:00 airlied@pdx.freedesktop.org +25 -9
#   * Introduce COMMIT_RING() as in radeon DRM, stop using error prone
#     writeback for ring read pointer (Paul Mackerras)
#   * Get rid of some superfluous stuff, minor fixes
# 
# drivers/char/drm/r128_drv.h
#   2004/04/10 06:27:19-07:00 airlied@pdx.freedesktop.org +32 -25
#   * Introduce COMMIT_RING() as in radeon DRM, stop using error prone
#     writeback for ring read pointer (Paul Mackerras)
#   * Get rid of some superfluous stuff, minor fixes
# 
# drivers/char/drm/r128_cce.c
#   2004/04/10 06:27:19-07:00 airlied@pdx.freedesktop.org +9 -30
#   * Introduce COMMIT_RING() as in radeon DRM, stop using error prone
#     writeback for ring read pointer (Paul Mackerras)
#   * Get rid of some superfluous stuff, minor fixes
# 
# ChangeSet
#   2004/04/10 05:26:04-07:00 airlied@pdx.freedesktop.org 
#   radeon_drm.h:
#     missing define from previous checkin
# 
# drivers/char/drm/radeon_drm.h
#   2004/04/10 05:25:29-07:00 airlied@pdx.freedesktop.org +1 -0
#   missing define from previous checkin
# 
# ChangeSet
#   2004/04/10 00:52:10-07:00 airlied@pdx.freedesktop.org 
#   Miscellaneous changes from DRM CVS
# 
# drivers/char/drm/drm_stub.h
#   2004/04/10 00:52:04-07:00 airlied@pdx.freedesktop.org +2 -2
#   retab..
# 
# drivers/char/drm/drm_bufs.h
#   2004/04/10 00:52:04-07:00 airlied@pdx.freedesktop.org +1 -1
#   use correct preproc directive..
# 
# drivers/char/drm/drm_agpsupport.h
#   2004/04/10 00:52:04-07:00 airlied@pdx.freedesktop.org +2 -0
#   add another error test for 2.6
# 
# drivers/char/drm/drmP.h
#   2004/04/10 00:52:04-07:00 airlied@pdx.freedesktop.org +0 -12
#   move lock to drm.h
# 
# drivers/char/drm/drm.h
#   2004/04/10 00:52:04-07:00 airlied@pdx.freedesktop.org +14 -2
#   move the lcok to drm.h align some preprocesor stuff 
# 
# ChangeSet
#   2004/04/10 00:06:33-07:00 airlied@pdx.freedesktop.org 
#   drm_ctx_dtor.patch
#   Submitted by: Erdi Chen
# 
# drivers/char/drm/drm_memory_debug.h
#   2004/04/10 00:06:27-07:00 airlied@pdx.freedesktop.org +1 -0
#   drm_ctx_dtor.patch
#   Submitted by: Erdi Chen
# 
# drivers/char/drm/drm_drv.h
#   2004/04/10 00:06:27-07:00 airlied@pdx.freedesktop.org +27 -0
#   drm_ctx_dtor.patch
#   Submitted by: Erdi Chen
# 
# drivers/char/drm/drm_context.h
#   2004/04/10 00:06:27-07:00 airlied@pdx.freedesktop.org +29 -0
#   drm_ctx_dtor.patch
#   Submitted by: Erdi Chen
# 
# drivers/char/drm/drmP.h
#   2004/04/10 00:06:27-07:00 airlied@pdx.freedesktop.org +16 -0
#   drm_ctx_dtor.patch
#   Submitted by: Erdi Chen
# 
# ChangeSet
#   2004/04/09 23:56:13-07:00 airlied@pdx.freedesktop.org 
#   More differentiated error codes for DRM(agp_acquire)
# 
# drivers/char/drm/drm_agpsupport.h
#   2004/04/09 23:56:07-07:00 airlied@pdx.freedesktop.org +5 -1
#   More differentiated error codes for DRM(agp_acquire)
# 
# ChangeSet
#   2004/04/09 23:44:36-07:00 airlied@pdx.freedesktop.org 
#   From Michel Daenzer:
#   Adapt to nopage() prototype change in Linux 2.6.1.
#   
#   Reviewed by: Arjan van de Ven <arjanv@redhat.com>, additional feedback
#   from William Lee Irwin III and Linus Torvalds.
# 
# drivers/char/drm/drm_vm.h
#   2004/04/09 23:44:27-07:00 airlied@pdx.freedesktop.org +97 -51
#   From Michel Daenzer:
#   Adapt to nopage() prototype change in Linux 2.6.1.
#   
#   Reviewed by: Arjan van de Ven <arjanv@redhat.com>, additional feedback
#   from William Lee Irwin III and Linus Torvalds.
# 
# drivers/char/drm/drmP.h
#   2004/04/09 23:44:27-07:00 airlied@pdx.freedesktop.org +0 -12
#   From Michel Daenzer:
#   Adapt to nopage() prototype change in Linux 2.6.1.
#   
#   Reviewed by: Arjan van de Ven <arjanv@redhat.com>, additional feedback
#   from William Lee Irwin III and Linus Torvalds.
# 
# ChangeSet
#   2004/04/09 23:20:06-07:00 airlied@pdx.freedesktop.org 
#   From Eric Anholt + Jon Smirl:
#   Don't ioremap the framebuffer area. The ioremapped area wasn't used by
#   anything.
# 
# drivers/char/drm/radeon_drv.h
#   2004/04/09 23:19:59-07:00 airlied@pdx.freedesktop.org +0 -1
#   From Eric Anholt + Jon Smirl:
#   Don't ioremap the framebuffer area. The ioremapped area wasn't used by
#   anything.
# 
# drivers/char/drm/radeon_cp.c
#   2004/04/09 23:19:59-07:00 airlied@pdx.freedesktop.org +0 -7
#   From Eric Anholt + Jon Smirl:
#   Don't ioremap the framebuffer area. The ioremapped area wasn't used by
#   anything.
# 
# drivers/char/drm/r128_drv.h
#   2004/04/09 23:19:59-07:00 airlied@pdx.freedesktop.org +0 -1
#   From Eric Anholt + Jon Smirl:
#   Don't ioremap the framebuffer area. The ioremapped area wasn't used by
#   anything.
# 
# drivers/char/drm/r128_cce.c
#   2004/04/09 23:19:59-07:00 airlied@pdx.freedesktop.org +0 -7
#   From Eric Anholt + Jon Smirl:
#   Don't ioremap the framebuffer area. The ioremapped area wasn't used by
#   anything.
# 
# drivers/char/drm/mga_drv.h
#   2004/04/09 23:19:59-07:00 airlied@pdx.freedesktop.org +0 -1
#   From Eric Anholt + Jon Smirl:
#   Don't ioremap the framebuffer area. The ioremapped area wasn't used by
#   anything.
# 
# drivers/char/drm/mga_dma.c
#   2004/04/09 23:19:59-07:00 airlied@pdx.freedesktop.org +0 -8
#   From Eric Anholt + Jon Smirl:
#   Don't ioremap the framebuffer area. The ioremapped area wasn't used by
#   anything.
# 
# drivers/char/drm/drm_bufs.h
#   2004/04/09 23:19:58-07:00 airlied@pdx.freedesktop.org +3 -1
#   From Eric Anholt + Jon Smirl:
#   Don't ioremap the framebuffer area. The ioremapped area wasn't used by
#   anything.
# 
# ChangeSet
#   2004/04/09 23:07:59-07:00 airlied@pdx.freedesktop.org 
#   From Eric Anholt:
#   Return EBUSY when attempting to addmap a DRM_SHM area with a lock in it if
#   dev->lock.hw_lock is already set. This fixes the case of two X Servers running
#   on the same head on different VTs with interface 1.1, by making the 2nd head
#   fail to inizialize like before.
# 
# drivers/char/drm/drm_bufs.h
#   2004/04/09 23:07:52-07:00 airlied@pdx.freedesktop.org +6 -0
#   From Eric Anholt:
#   Return EBUSY when attempting to addmap a DRM_SHM area with a lock in it if
#   dev->lock.hw_lock is already set. This fixes the case of two X Servers running
#   on the same head on different VTs with interface 1.1, by making the 2nd head
#   fail to inizialize like before.
# 
# ChangeSet
#   2004/04/09 23:00:48-07:00 airlied@pdx.freedesktop.org 
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/radeon_cp.c
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +1 -1
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/r128_cce.c
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +1 -1
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/mga_dma.c
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +1 -1
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/i830_dma.c
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +2 -2
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/i810_dma.c
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +1 -1
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/gamma_dma.c
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +1 -1
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/drm_irq.h
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +57 -18
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/drm_ioctl.h
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +36 -137
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/drm_drv.h
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +14 -4
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# drivers/char/drm/drmP.h
#   2004/04/09 23:00:37-07:00 airlied@pdx.freedesktop.org +12 -4
#   From Eric Anholt: some cleanups from AlanH:
#   - Tie the DRM to a specific device: setunique no longer succeeds when given
#   a busid that doesn't correspond to the device the DRM is attached to. This
#   is a breaking of backwards-compatibility only for the multiple-DRI-head case
#   with X Servers that don't use interface 1.1.
#   - Move irq_busid to drm_irq.h and make it only return the IRQ for the current
#   device. Retains compatibility with previous X Servers, cleans up unnecessary
#   code. This means no irq_busid on !__HAVE_IRQ, but can be changed if
#   necessary.
#   - Bump interface version to 1.2. This version when set signifies that the
#   control ioctl should ignore the irq number passed in and enable the
#   interrupt handler for the attached device. Otherwise it errors out when
#   the passed-in irq is not equal to the device's.
#   - Store the highest version the interface has been set to in the device. 
# 
# ChangeSet
#   2004/04/09 22:34:54-07:00 airlied@pdx.freedesktop.org 
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/radeon_state.c
#   2004/04/09 22:34:48-07:00 airlied@pdx.freedesktop.org +370 -42
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/radeon_drv.h
#   2004/04/09 22:34:47-07:00 airlied@pdx.freedesktop.org +5 -0
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/radeon_drm.h
#   2004/04/09 22:34:47-07:00 airlied@pdx.freedesktop.org +14 -1
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/radeon_cp.c
#   2004/04/09 22:34:47-07:00 airlied@pdx.freedesktop.org +20 -9
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/radeon.h
#   2004/04/09 22:34:47-07:00 airlied@pdx.freedesktop.org +19 -3
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/drm_os_linux.h
#   2004/04/09 22:34:47-07:00 airlied@pdx.freedesktop.org +4 -0
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/drm_fops.h
#   2004/04/09 22:34:47-07:00 airlied@pdx.freedesktop.org +2 -0
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/drm_drv.h
#   2004/04/09 22:34:47-07:00 airlied@pdx.freedesktop.org +3 -0
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# drivers/char/drm/drmP.h
#   2004/04/09 22:34:47-07:00 airlied@pdx.freedesktop.org +3 -0
#   From: Michel Daenzer:
#   Memory layout transition:
#   
#   * the 2D driver initializes MC_FB_LOCATION and related registers sanely
#   * the DRM deduces the layout from these registers
#   * clients use the new SETPARAM ioctl to tell the DRM where they think the
#   framebuffer is located in the card's address space
#   * the DRM uses all this information to check client state and fix it up if
#   necessary
#   
#   This is a prerequisite for things like direct rendering with IGP chips and
#   video capturing.
# 
# ChangeSet
#   2004/04/09 21:32:02-07:00 airlied@pdx.freedesktop.org 
#   From Eric Anholt:
#    Introduce a new ioctl, DRM_IOCTL_SET_VERSION. This ioctl allows the server
#   or client to notify the DRM that it expects a certain version of the device
#   dependent or device independent interface. If the major doesn't match or minor
#   is too large, EINVAL is returned. A major of -1 means that the requestor
#   doesn't care about that portion of the interface. The ioctl returns the actual
#   versions in the same struct. 
# 
# drivers/char/drm/drm_ioctl.h
#   2004/04/09 21:28:47-07:00 airlied@pdx.freedesktop.org +74 -1
#   From Eric Anholt:
#    Introduce a new ioctl, DRM_IOCTL_SET_VERSION. This ioctl allows the server
#   or client to notify the DRM that it expects a certain version of the device
#   dependent or device independent interface. If the major doesn't match or minor
#   is too large, EINVAL is returned. A major of -1 means that the requestor
#   doesn't care about that portion of the interface. The ioctl returns the actual
#   versions in the same struct. 
# 
# drivers/char/drm/drm_drv.h
#   2004/04/09 21:28:47-07:00 airlied@pdx.freedesktop.org +1 -0
#   From Eric Anholt:
#    Introduce a new ioctl, DRM_IOCTL_SET_VERSION. This ioctl allows the server
#   or client to notify the DRM that it expects a certain version of the device
#   dependent or device independent interface. If the major doesn't match or minor
#   is too large, EINVAL is returned. A major of -1 means that the requestor
#   doesn't care about that portion of the interface. The ioctl returns the actual
#   versions in the same struct. 
# 
# drivers/char/drm/drmP.h
#   2004/04/09 21:28:47-07:00 airlied@pdx.freedesktop.org +2 -0
#   From Eric Anholt:
#    Introduce a new ioctl, DRM_IOCTL_SET_VERSION. This ioctl allows the server
#   or client to notify the DRM that it expects a certain version of the device
#   dependent or device independent interface. If the major doesn't match or minor
#   is too large, EINVAL is returned. A major of -1 means that the requestor
#   doesn't care about that portion of the interface. The ioctl returns the actual
#   versions in the same struct. 
# 
# drivers/char/drm/drm.h
#   2004/04/09 21:28:47-07:00 airlied@pdx.freedesktop.org +11 -0
#   From Eric Anholt:
#    Introduce a new ioctl, DRM_IOCTL_SET_VERSION. This ioctl allows the server
#   or client to notify the DRM that it expects a certain version of the device
#   dependent or device independent interface. If the major doesn't match or minor
#   is too large, EINVAL is returned. A major of -1 means that the requestor
#   doesn't care about that portion of the interface. The ioctl returns the actual
#   versions in the same struct. 
# 
# ChangeSet
#   2004/04/09 20:03:25-07:00 airlied@pdx.freedesktop.org 
#   - Add DRM_GET_PRIV_WITH_RETURN macro. This can be used in shared code to get
#   the drm_file_t * based on the filp passed in ioctl handlers. 
# 
# drivers/char/drm/drm_os_linux.h
#   2004/04/09 20:03:19-07:00 airlied@pdx.freedesktop.org +2 -0
#   - Add DRM_GET_PRIV_WITH_RETURN macro. This can be used in shared code to get
#   the drm_file_t * based on the filp passed in ioctl handlers. 
# 
# ChangeSet
#   2004/04/09 19:35:05-07:00 airlied@pdx.freedesktop.org 
#   left gamma_dma.c out of last changeset
# 
# drivers/char/drm/gamma_dma.c
#   2004/04/09 19:34:58-07:00 airlied@pdx.freedesktop.org +3 -3
#   FRom Eric Anholt:
#    Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit.
# 
# ChangeSet
#   2004/04/09 19:12:53-07:00 airlied@pdx.freedesktop.org 
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/drm_irq.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +333 -0
# 
# drivers/char/drm/radeon_irq.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/radeon_drv.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -0
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/radeon_cp.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/radeon.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/r128_irq.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/r128_drv.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -0
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/r128_cce.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/r128.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/mga_irq.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/mga_drv.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -0
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/mga_dma.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/mga.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/i830_irq.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/i830_drv.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -0
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/i830_dma.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/i830.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +2 -2
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/i810_dma.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/i810.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -1
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/gamma_drv.c
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +1 -0
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/gamma.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +2 -2
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/drm_irq.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +0 -0
#   BitKeeper file /home/airlied/linux/drm-dev/drivers/char/drm/drm_irq.h
# 
# drivers/char/drm/drm_drv.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +6 -6
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/drm_dma.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +5 -298
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# drivers/char/drm/drmP.h
#   2004/04/09 19:12:45-07:00 airlied@pdx.freedesktop.org +11 -7
#   From: Eric Anholt:
#   - Move IRQ functions from drm_dma.h to new drm_irq.h and disentangle them from
#   __HAVE_DMA. This will be useful for adding vblank sync support to sis and
#   tdfx. Rename dma_service to irq_handler, which is more accurately what it is.
#   - Fix the #if _HAVE_DMA_IRQ in radeon, r128, mga, i810, i830, gamma to have
#   the right number of underscores. This may have been a problem in the case
#   that the server died without doing its DRM_IOCTL_CONTROL to uninit
# 
# ChangeSet
#   2004/04/09 00:28:45-07:00 airlied@pdx.freedesktop.org 
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial. clean up tdfx to look like everyone else..
# 
# drivers/char/drm/tdfx_drv.c
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +0 -41
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial. clean up tdfx to look like everyone else..
# 
# drivers/char/drm/tdfx.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +18 -0
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial. clean up tdfx to look like everyone else..
# 
# drivers/char/drm/sis.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +7 -0
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
# drivers/char/drm/radeon.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +60 -1
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
# drivers/char/drm/r128.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +40 -0
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
# drivers/char/drm/mga.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +6 -0
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
# drivers/char/drm/i830.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +7 -0
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
# drivers/char/drm/i810.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +8 -1
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
# drivers/char/drm/gamma.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +4 -0
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
# drivers/char/drm/drm_drv.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +87 -115
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
# drivers/char/drm/drmP.h
#   2004/04/09 00:28:35-07:00 airlied@pdx.freedesktop.org +7 -4
#   - Converted Linux drivers to initialize DRM instances based on PCI IDs, not
#   just a single instance. The PCI ID lists include a driver private field, which may be used
#   by drivers for chip family or other information. Based on work by jonsmirl
#   and Eric Anholt. I've left out the PCI device naming for this patch as
#   that might be a bit controversial.
# 
diff -Nru a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
--- a/drivers/char/drm/drm.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm.h	Wed Apr 14 18:25:42 2004
@@ -46,8 +46,8 @@
 #define DRM_IOC_WRITE		_IOC_WRITE
 #define DRM_IOC_READWRITE	_IOC_READ|_IOC_WRITE
 #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
-#elif defined(__FreeBSD__) || defined(__NetBSD__)
-#if defined(__FreeBSD__) && defined(XFree86Server)
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#if defined(__FreeBSD__) && defined(IN_MODULE)
 /* Prevent name collision when including sys/ioccom.h */
 #undef ioctl
 #include <sys/ioccom.h>
@@ -130,6 +130,18 @@
 	unsigned int	age;
 } drm_tex_region_t;
 
+/**
+ * Hardware lock.
+ *
+ * The lock structure is a simple cache-line aligned integer.  To avoid
+ * processor bus contention on a multiprocessor system, there should not be any
+ * other data stored in the same cache line.
+ */
+typedef struct drm_hw_lock {
+	__volatile__ unsigned int lock;		/**< lock variable */
+	char			  padding[60];	/**< Pad to cache line */
+} drm_hw_lock_t;
+
 
 /**
  * DRM_IOCTL_VERSION ioctl argument type.
@@ -580,6 +592,16 @@
 	unsigned long handle;	/**< Used for mapping / unmapping */
 } drm_scatter_gather_t;
 
+/**
+ * DRM_IOCTL_SET_VERSION ioctl argument type.
+ */
+typedef struct drm_set_version {
+	int drm_di_major;
+	int drm_di_minor;
+	int drm_dd_major;
+	int drm_dd_minor;
+} drm_set_version_t;
+
 
 #define DRM_IOCTL_BASE			'd'
 #define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
@@ -594,6 +616,7 @@
 #define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, drm_map_t)
 #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, drm_client_t)
 #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, drm_stats_t)
+#define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, drm_set_version_t)
 
 #define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, drm_unique_t)
 #define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, drm_auth_t)
diff -Nru a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
--- a/drivers/char/drm/drmP.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drmP.h	Wed Apr 14 18:25:42 2004
@@ -92,8 +92,8 @@
 #ifndef __HAVE_DMA
 #define __HAVE_DMA		0
 #endif
-#ifndef __HAVE_DMA_IRQ
-#define __HAVE_DMA_IRQ		0
+#ifndef __HAVE_IRQ
+#define __HAVE_IRQ		0
 #endif
 #ifndef __HAVE_DMA_WAITLIST
 #define __HAVE_DMA_WAITLIST	0
@@ -148,6 +148,7 @@
 #define DRM_MEM_CTXBITMAP 18
 #define DRM_MEM_STUB      19
 #define DRM_MEM_SGLISTS   20
+#define DRM_MEM_CTXLIST  21
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 	
@@ -324,6 +325,7 @@
 #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
 #define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
 
+#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
 /**
  * Get the private SAREA mapping.
  *
@@ -362,10 +364,12 @@
 typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg );
 
-typedef struct drm_pci_list {
-	u16 vendor;
-	u16 device;
-} drm_pci_list_t;
+typedef struct drm_pci_id_list
+{
+	int vendor;
+	int device;
+	long driver_private;
+} drm_pci_id_list_t;
 
 typedef struct drm_ioctl_desc {
 	drm_ioctl_t	     *func;
@@ -463,18 +467,6 @@
 	drm_freelist_t	  freelist;
 } drm_buf_entry_t;
 
-/**
- * Hardware lock.
- *
- * The lock structure is a simple cache-line aligned integer.  To avoid
- * processor bus contention on a multiprocessor system, there should not be any
- * other data stored in the same cache line.
- */
-typedef struct drm_hw_lock {
-	__volatile__ unsigned int lock;		/**< lock variable */
-	char			  padding[60];	/**< Pad to cache line */
-} drm_hw_lock_t;
-
 /** File private data */
 typedef struct drm_file {
 	int		  authenticated;
@@ -488,6 +480,9 @@
 	struct drm_device *dev;
 	int 		  remove_auth_on_close;
 	unsigned long     lock_count;
+#ifdef DRIVER_FILE_FIELDS
+	DRIVER_FILE_FIELDS;
+#endif
 } drm_file_t;
 
 /** Wait queue */
@@ -602,6 +597,15 @@
 
 typedef drm_map_t drm_local_map_t;
 
+/**
+ * Context handle list
+ */
+typedef struct drm_ctx_list {
+	struct list_head	head;   /**< list head */
+	drm_context_t		handle; /**< context handle */
+	drm_file_t		*tag;   /**< associated fd private data */
+} drm_ctx_list_t;
+
 #if __HAVE_VBL_IRQ
 
 typedef struct drm_vbl_sig {
@@ -622,6 +626,8 @@
 	int		  unique_len;	/**< Length of unique field */
 	dev_t		  device;	/**< Device number for mknod */
 	char		  *devname;	/**< For /proc/interrupts */
+	int		  minor;        /**< Minor device number */
+	int		  if_version;	/**< Highest interface version set */
 
 	int		  blocked;	/**< Blocked due to VC switch? */
 	struct proc_dir_entry *root;	/**< Root for this device's entries */
@@ -660,6 +666,12 @@
 	drm_map_list_t	  *maplist;	/**< Linked list of regions */
 	int		  map_count;	/**< Number of mappable regions */
 
+	/** \name Context handle management */
+	/*@{*/
+	drm_ctx_list_t	  *ctxlist;	/**< Linked list of context handles */
+	int		  ctx_count;	/**< Number of context handles */
+	struct semaphore  ctxlist_sem;	/**< For ctxlist */
+
 	drm_map_t	  **context_sareas; /**< per-context SAREA's */
 	int		  max_context;
 
@@ -679,6 +691,7 @@
 	/** \name Context support */
 	/*@{*/
 	int		  irq;		/**< Interrupt used by board */
+	int		  irq_enabled;	/**< True if irq handler is enabled */
 	__volatile__ long context_flag;	/**< Context swapping flag */
 	__volatile__ long interrupt_flag; /**< Interruption handler flag */
 	__volatile__ long dma_flag;	/**< DMA dispatch flag */
@@ -714,7 +727,12 @@
 #if __REALLY_HAVE_AGP
 	drm_agp_head_t    *agp;	/**< AGP data */
 #endif
-	struct pci_dev *pdev;		/**< PCI device structure */
+
+	struct pci_dev    *pdev;	/**< PCI device structure */
+	int               pci_domain;	/**< PCI bus domain number */
+	int               pci_bus;	/**< PCI bus number */
+	int               pci_slot;	/**< PCI slot number */
+	int               pci_func;	/**< PCI function number */
 #ifdef __alpha__
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
 	struct pci_controler *hose;
@@ -758,18 +776,6 @@
 extern int	     DRM(fasync)(int fd, struct file *filp, int on);
 
 				/* Mapping support (drm_vm.h) */
-extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
-				   unsigned long address,
-				   int *type);
-extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
-				       unsigned long address,
-				       int *type);
-extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
-				       unsigned long address,
-				       int *type);
-extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
-				      unsigned long address,
-				      int *type);
 extern void	     DRM(vm_open)(struct vm_area_struct *vma);
 extern void	     DRM(vm_close)(struct vm_area_struct *vma);
 extern void	     DRM(vm_shm_close)(struct vm_area_struct *vma);
@@ -804,8 +810,8 @@
 #endif
 
 				/* Misc. IOCTL support (drm_ioctl.h) */
-extern int	     DRM(irq_busid)(struct inode *inode, struct file *filp,
-				    unsigned int cmd, unsigned long arg);
+extern int	     DRM(irq_by_busid)(struct inode *inode, struct file *filp,
+				       unsigned int cmd, unsigned long arg);
 extern int	     DRM(getunique)(struct inode *inode, struct file *filp,
 				    unsigned int cmd, unsigned long arg);
 extern int	     DRM(setunique)(struct inode *inode, struct file *filp,
@@ -816,6 +822,8 @@
 				    unsigned int cmd, unsigned long arg);
 extern int	     DRM(getstats)(struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg);
+extern int	     DRM(setversion)(struct inode *inode, struct file *filp,
+				     unsigned int cmd, unsigned long arg);
 
 				/* Context IOCTL support (drm_context.h) */
 extern int	     DRM(resctx)( struct inode *inode, struct file *filp,
@@ -900,12 +908,17 @@
 extern void	     DRM(dma_takedown)(drm_device_t *dev);
 extern void	     DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
 extern void	     DRM(reclaim_buffers)( struct file *filp );
-#if __HAVE_DMA_IRQ
+#endif /* __HAVE_DMA */
+
+				/* IRQ support (drm_irq.h) */
+#if __HAVE_IRQ || __HAVE_DMA
 extern int           DRM(control)( struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg );
-extern int           DRM(irq_install)( drm_device_t *dev, int irq );
+#endif
+#if __HAVE_IRQ
+extern int           DRM(irq_install)( drm_device_t *dev );
 extern int           DRM(irq_uninstall)( drm_device_t *dev );
-extern irqreturn_t   DRM(dma_service)( DRM_IRQ_ARGS );
+extern irqreturn_t   DRM(irq_handler)( DRM_IRQ_ARGS );
 extern void          DRM(driver_irq_preinstall)( drm_device_t *dev );
 extern void          DRM(driver_irq_postinstall)( drm_device_t *dev );
 extern void          DRM(driver_irq_uninstall)( drm_device_t *dev );
@@ -915,12 +928,11 @@
 extern int           DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
 extern void          DRM(vbl_send_signals)( drm_device_t *dev );
 #endif
-#if __HAVE_DMA_IRQ_BH
-extern void          DRM(dma_immediate_bh)( void *dev );
+#if __HAVE_IRQ_BH
+extern void          DRM(irq_immediate_bh)( void *dev );
 #endif
 #endif
 
-#endif /* __HAVE_DMA */
 
 #if __REALLY_HAVE_AGP
 				/* AGP/GART support (drm_agpsupport.h) */
diff -Nru a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h
--- a/drivers/char/drm/drm_agpsupport.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_agpsupport.h	Wed Apr 14 18:25:42 2004
@@ -103,7 +103,13 @@
 	drm_device_t	 *dev	 = priv->dev;
 	int              retcode;
 
-	if (!dev->agp || dev->agp->acquired || !drm_agp->acquire)
+	if (!dev->agp)
+		return -ENODEV;
+	if (dev->agp->acquired)
+		return -EBUSY;
+	if (!drm_agp->acquire)
+		return -EINVAL;
+	if ( dev->agp->cant_use_aperture )
 		return -EINVAL;
 	if ((retcode = drm_agp->acquire()))
 		return retcode;
diff -Nru a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h
--- a/drivers/char/drm/drm_bufs.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_bufs.h	Wed Apr 14 18:25:42 2004
@@ -147,7 +147,9 @@
 					      MTRR_TYPE_WRCOMB, 1 );
 		}
 #endif
-		map->handle = DRM(ioremap)( map->offset, map->size, dev );
+		if (map->type == _DRM_REGISTERS)
+			map->handle = DRM(ioremap)( map->offset, map->size,
+						    dev );
 		break;
 
 	case _DRM_SHM:
@@ -160,6 +162,12 @@
 		}
 		map->offset = (unsigned long)map->handle;
 		if ( map->flags & _DRM_CONTAINS_LOCK ) {
+			/* Prevent a 2nd X Server from creating a 2nd lock */
+			if (dev->lock.hw_lock != NULL) {
+				vfree( map->handle );
+				DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+				return -EBUSY;
+			}
 			dev->sigdata.lock =
 			dev->lock.hw_lock = map->handle; /* Pointer to lock */
 		}
@@ -767,7 +775,7 @@
 }
 #endif /* __HAVE_PCI_DMA */
 
-#ifdef __HAVE_SG
+#if __HAVE_SG
 int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg )
 {
diff -Nru a/drivers/char/drm/drm_context.h b/drivers/char/drm/drm_context.h
--- a/drivers/char/drm/drm_context.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_context.h	Wed Apr 14 18:25:42 2004
@@ -401,6 +401,7 @@
 {
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
+	drm_ctx_list_t * ctx_entry;
 	drm_ctx_t ctx;
 
 	if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
@@ -421,6 +422,20 @@
 	if ( ctx.handle != DRM_KERNEL_CONTEXT )
 		DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
 #endif
+	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 = priv;
+
+	down( &dev->ctxlist_sem );
+	list_add( &ctx_entry->head, &dev->ctxlist->head );
+	++dev->ctx_count;
+	up( &dev->ctxlist_sem );
 
 	if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
 		return -EFAULT;
@@ -542,6 +557,20 @@
 #endif
 		DRM(ctxbitmap_free)( dev, ctx.handle );
 	}
+
+	down( &dev->ctxlist_sem );
+	if ( !list_empty( &dev->ctxlist->head ) ) {
+		drm_ctx_list_t *pos, *n;
+
+		list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+			if ( pos->handle == ctx.handle ) {
+				list_del( &pos->head );
+				DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+				--dev->ctx_count;
+			}
+		}
+	}
+	up( &dev->ctxlist_sem );
 
 	return 0;
 }
diff -Nru a/drivers/char/drm/drm_dma.h b/drivers/char/drm/drm_dma.h
--- a/drivers/char/drm/drm_dma.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_dma.h	Wed Apr 14 18:25:42 2004
@@ -35,7 +35,6 @@
 
 #include "drmP.h"
 
-#include <linux/interrupt.h>	/* For task queue support */
 
 #ifndef __HAVE_DMA_WAITQUEUE
 #define __HAVE_DMA_WAITQUEUE	0
@@ -43,15 +42,6 @@
 #ifndef __HAVE_DMA_RECLAIM
 #define __HAVE_DMA_RECLAIM	0
 #endif
-#ifndef __HAVE_SHARED_IRQ
-#define __HAVE_SHARED_IRQ	0
-#endif
-
-#if __HAVE_SHARED_IRQ
-#define DRM_IRQ_TYPE		SA_SHIRQ
-#else
-#define DRM_IRQ_TYPE		0
-#endif
 
 #if __HAVE_DMA
 
@@ -214,293 +204,11 @@
 }
 #endif
 
-
-
-
-#if __HAVE_DMA_IRQ
-
-/**
- * Install IRQ handler.
- *
- * \param dev DRM device.
- * \param irq IRQ number.
- *
- * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
- * \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions
- * before and after the installation.
- */
-int DRM(irq_install)( drm_device_t *dev, int irq )
-{
-	int ret;
-
-	if ( !irq )
-		return -EINVAL;
-
-	down( &dev->struct_sem );
-
-	/* Driver must have been initialized */
-	if ( !dev->dev_private ) {
-		up( &dev->struct_sem );
-		return -EINVAL;
-	}
-
-	if ( dev->irq ) {
-		up( &dev->struct_sem );
-		return -EBUSY;
-	}
-	dev->irq = irq;
-	up( &dev->struct_sem );
-
-	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
-
-	dev->context_flag = 0;
-	dev->interrupt_flag = 0;
-	dev->dma_flag = 0;
-
-	dev->dma->next_buffer = NULL;
-	dev->dma->next_queue = NULL;
-	dev->dma->this_buffer = NULL;
-
-#if __HAVE_DMA_IRQ_BH
-	INIT_WORK(&dev->work, DRM(dma_immediate_bh), dev);
-#endif
-
-#if __HAVE_VBL_IRQ
-	init_waitqueue_head(&dev->vbl_queue);
-
-	spin_lock_init( &dev->vbl_lock );
-
-	INIT_LIST_HEAD( &dev->vbl_sigs.head );
-
-	dev->vbl_pending = 0;
-#endif
-
-				/* Before installing handler */
-	DRM(driver_irq_preinstall)(dev);
-
-				/* Install handler */
-	ret = request_irq( dev->irq, DRM(dma_service),
-			   DRM_IRQ_TYPE, dev->devname, dev );
-	if ( ret < 0 ) {
-		down( &dev->struct_sem );
-		dev->irq = 0;
-		up( &dev->struct_sem );
-		return ret;
-	}
-
-				/* After installing handler */
-	DRM(driver_irq_postinstall)(dev);
-
-	return 0;
-}
-
-/**
- * Uninstall the IRQ handler.
- *
- * \param dev DRM device.
- *
- * Calls the driver's \c DRM(driver_irq_uninstall)() function, and stops the irq.
- */
-int DRM(irq_uninstall)( drm_device_t *dev )
-{
-	int irq;
-
-	down( &dev->struct_sem );
-	irq = dev->irq;
-	dev->irq = 0;
-	up( &dev->struct_sem );
-
-	if ( !irq )
-		return -EINVAL;
-
-	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
-
-	DRM(driver_irq_uninstall)( dev );
-
-	free_irq( irq, dev );
-
-	return 0;
-}
-
-/**
- * IRQ control ioctl.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_control structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls irq_install() or irq_uninstall() according to \p arg.
- */
-int DRM(control)( struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg )
-{
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
-	drm_control_t ctl;
-
-	if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
-		return -EFAULT;
-
-	switch ( ctl.func ) {
-	case DRM_INST_HANDLER:
-		return DRM(irq_install)( dev, ctl.irq );
-	case DRM_UNINST_HANDLER:
-		return DRM(irq_uninstall)( dev );
-	default:
-		return -EINVAL;
-	}
-}
-
-#if __HAVE_VBL_IRQ
-
-/**
- * Wait for VBLANK.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param data user argument, pointing to a drm_wait_vblank structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the IRQ is installed. 
- *
- * If a signal is requested checks if this task has already scheduled the same signal
- * for the same vblank sequence number - nothing to be done in
- * that case. If the number of tasks waiting for the interrupt exceeds 100 the
- * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
- * task.
- *
- * If a signal is not requested, then calls vblank_wait().
- */
-int DRM(wait_vblank)( DRM_IOCTL_ARGS )
-{
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
-	drm_wait_vblank_t vblwait;
-	struct timeval now;
-	int ret = 0;
-	unsigned int flags;
-
-	if (!dev->irq)
-		return -EINVAL;
-
-	DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
-				  sizeof(vblwait) );
-
-	switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
-	case _DRM_VBLANK_RELATIVE:
-		vblwait.request.sequence += atomic_read( &dev->vbl_received );
-		vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
-	case _DRM_VBLANK_ABSOLUTE:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
-	
-	if ( flags & _DRM_VBLANK_SIGNAL ) {
-		unsigned long irqflags;
-		drm_vbl_sig_t *vbl_sig;
-		
-		vblwait.reply.sequence = atomic_read( &dev->vbl_received );
-
-		spin_lock_irqsave( &dev->vbl_lock, irqflags );
-
-		/* Check if this task has already scheduled the same signal
-		 * for the same vblank sequence number; nothing to be done in
-		 * that case
-		 */
-		list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
-			if (vbl_sig->sequence == vblwait.request.sequence
-			    && vbl_sig->info.si_signo == vblwait.request.signal
-			    && vbl_sig->task == current)
-			{
-				spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
-				goto done;
-			}
-		}
-
-		if ( dev->vbl_pending >= 100 ) {
-			spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
-			return -EBUSY;
-		}
-
-		dev->vbl_pending++;
-
-		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
-
-		if ( !( vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) ) ) ) {
-			return -ENOMEM;
-		}
-
-		memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
-
-		vbl_sig->sequence = vblwait.request.sequence;
-		vbl_sig->info.si_signo = vblwait.request.signal;
-		vbl_sig->task = current;
-
-		spin_lock_irqsave( &dev->vbl_lock, irqflags );
-
-		list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
-
-		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
-	} else {
-		ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
-
-		do_gettimeofday( &now );
-		vblwait.reply.tval_sec = now.tv_sec;
-		vblwait.reply.tval_usec = now.tv_usec;
-	}
-
-done:
-	DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
-				sizeof(vblwait) );
-
-	return ret;
-}
-
-/**
- * Send the VBLANK signals.
- *
- * \param dev DRM device.
- *
- * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
- *
- * If a signal is not requested, then calls vblank_wait().
+#if !__HAVE_IRQ
+/* This stub DRM_IOCTL_CONTROL handler is for the drivers that used to require
+ * IRQs for DMA but no longer do.  It maintains compatibility with the X Servers
+ * that try to use the control ioctl by simply returning success.
  */
-void DRM(vbl_send_signals)( drm_device_t *dev )
-{
-	struct list_head *list, *tmp;
-	drm_vbl_sig_t *vbl_sig;
-	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
-	unsigned long flags;
-
-	spin_lock_irqsave( &dev->vbl_lock, flags );
-
-	list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
-		vbl_sig = list_entry( list, drm_vbl_sig_t, head );
-		if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
-			vbl_sig->info.si_code = vbl_seq;
-			send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
-
-			list_del( list );
-
-			DRM_FREE( vbl_sig, sizeof(*vbl_sig) );
-
-			dev->vbl_pending--;
-		}
-	}
-
-	spin_unlock_irqrestore( &dev->vbl_lock, flags );
-}
-
-#endif	/* __HAVE_VBL_IRQ */
-
-#else
-
 int DRM(control)( struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg )
 {
@@ -517,7 +225,6 @@
 		return -EINVAL;
 	}
 }
-
-#endif /* __HAVE_DMA_IRQ */
+#endif
 
 #endif /* __HAVE_DMA */
diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h
--- a/drivers/char/drm/drm_drv.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_drv.h	Wed Apr 14 18:25:42 2004
@@ -58,8 +58,8 @@
 #ifndef __HAVE_CTX_BITMAP
 #define __HAVE_CTX_BITMAP		0
 #endif
-#ifndef __HAVE_DMA_IRQ
-#define __HAVE_DMA_IRQ			0
+#ifndef __HAVE_IRQ
+#define __HAVE_IRQ			0
 #endif
 #ifndef __HAVE_DMA_QUEUE
 #define __HAVE_DMA_QUEUE		0
@@ -126,6 +126,9 @@
 #ifndef DRIVER_IOCTLS
 #define DRIVER_IOCTLS
 #endif
+#ifndef DRIVER_OPEN_HELPER
+#define DRIVER_OPEN_HELPER( priv, dev )
+#endif
 #ifndef DRIVER_FOPS
 #define DRIVER_FOPS				\
 static struct file_operations	DRM(fops) = {	\
@@ -159,15 +162,8 @@
 #undef DRM_OPTIONS_FUNC
 #endif
 
-/**
- * The default number of instances (minor numbers) to initialize.
- */
-#ifndef DRIVER_NUM_CARDS
-#define DRIVER_NUM_CARDS 1
-#endif
-
-static drm_device_t	*DRM(device);
-static int		*DRM(minor);
+#define MAX_DEVICES 4
+static drm_device_t	DRM(device)[MAX_DEVICES];
 static int		DRM(numdevs) = 0;
 
 DRIVER_FOPS;
@@ -177,10 +173,13 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { DRM(version),     0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { DRM(getunique),   0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { DRM(getmagic),    0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_busid),   0, 1 },
+#if __HAVE_IRQ
+	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_by_busid), 0, 1 },
+#endif
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { DRM(getmap),      0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { DRM(getclient),   0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { DRM(getstats),    0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)]   = { DRM(setversion),  0, 1 },
 
 	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { DRM(setunique),   1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]         = { DRM(noop),        1, 1 },
@@ -222,9 +221,9 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { DRM(infobufs),    1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { DRM(mapbufs),     1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { DRM(freebufs),    1, 0 },
-
-	/* The DRM_IOCTL_DMA ioctl should be defined by the driver.
-	 */
+	/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
+#endif
+#if __HAVE_IRQ || __HAVE_DMA
 	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
 #endif
 
@@ -330,6 +329,12 @@
 	memset(dev->maplist, 0, sizeof(*dev->maplist));
 	INIT_LIST_HEAD(&dev->maplist->head);
 
+	dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist),
+				  DRM_MEM_CTXLIST);
+	if(dev->ctxlist == NULL) return -ENOMEM;
+	memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
+	INIT_LIST_HEAD(&dev->ctxlist->head);
+
 	dev->vmalist = NULL;
 	dev->sigdata.lock = dev->lock.hw_lock = NULL;
 	init_waitqueue_head( &dev->lock.lock_queue );
@@ -337,7 +342,7 @@
 	dev->queue_reserved = 0;
 	dev->queue_slots = 0;
 	dev->queuelist = NULL;
-	dev->irq = 0;
+	dev->irq_enabled = 0;
 	dev->context_flag = 0;
 	dev->interrupt_flag = 0;
 	dev->dma_flag = 0;
@@ -345,6 +350,7 @@
 	dev->last_switch = 0;
 	dev->last_checked = 0;
 	init_waitqueue_head( &dev->context_wait );
+	dev->if_version = 0;
 
 	dev->ctx_start = 0;
 	dev->lck_start = 0;
@@ -391,8 +397,8 @@
 	DRM_DEBUG( "\n" );
 
 	DRIVER_PRETAKEDOWN();
-#if __HAVE_DMA_IRQ
-	if ( dev->irq ) DRM(irq_uninstall)( dev );
+#if __HAVE_IRQ
+	if ( dev->irq_enabled ) DRM(irq_uninstall)( dev );
 #endif
 
 	down( &dev->struct_sem );
@@ -534,43 +540,101 @@
 	return 0;
 }
 
-/**
- * Figure out how many instances to initialize.
- *
- * \return number of cards found.
- *
- * Searches for every PCI card in \c DRIVER_CARD_LIST with matching vendor and device ids.
- */
-static int drm_count_cards(void)
+static drm_pci_id_list_t DRM(pciidlist)[] = {
+	DRIVER_PCI_IDS
+};
+
+static int DRM(probe)(struct pci_dev *pdev)
 {
-	int num = 0;
-#if defined(DRIVER_CARD_LIST)
-	int i;
-	drm_pci_list_t *l;
-	u16 device, vendor;
-	struct pci_dev *pdev = NULL;
+	drm_device_t *dev;
+#if __HAVE_CTX_BITMAP
+	int retcode;
 #endif
+	int i;
+	int is_compat = 0;
 
 	DRM_DEBUG( "\n" );
 
-#if defined(DRIVER_COUNT_CARDS)
-	num = DRIVER_COUNT_CARDS();
-#elif defined(DRIVER_CARD_LIST)
-	for (i = 0, l = DRIVER_CARD_LIST; l[i].vendor != 0; i++) {
-		pdev = NULL;
-		vendor = l[i].vendor;
-		device = l[i].device;
-		if(device == 0xffff) device = PCI_ANY_ID;
-		if(vendor == 0xffff) vendor = PCI_ANY_ID;
-		while ((pdev = pci_find_device(vendor, device, pdev))) {
-			num++;
+	for (i = 0; DRM(pciidlist)[i].vendor != 0; i++) {
+		if ((DRM(pciidlist)[i].vendor == pdev->vendor) &&
+		    (DRM(pciidlist)[i].device == pdev->device)) {
+			is_compat = 1;
 		}
 	}
+	if (is_compat == 0)
+		return -ENODEV;
+
+	if (DRM(numdevs) >= MAX_DEVICES)
+		return -ENODEV;
+
+	dev = &(DRM(device)[DRM(numdevs)]);
+
+	memset( (void *)dev, 0, sizeof(*dev) );
+	dev->count_lock = SPIN_LOCK_UNLOCKED;
+	init_timer( &dev->timer );
+	sema_init( &dev->struct_sem, 1 );
+	sema_init( &dev->ctxlist_sem, 1 );
+
+	if ((dev->minor = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
+		return -EPERM;
+	dev->device = MKDEV(DRM_MAJOR, dev->minor );
+	dev->name   = DRIVER_NAME;
+
+	dev->pdev   = pdev;
+#ifdef __alpha__
+	dev->hose   = pdev->sysdata;
+	dev->pci_domain = dev->hose->bus->number;
 #else
-	num = DRIVER_NUM_CARDS;
+	dev->pci_domain = 0;
+#endif
+	dev->pci_bus = pdev->bus->number;
+	dev->pci_slot = PCI_SLOT(pdev->devfn);
+	dev->pci_func = PCI_FUNC(pdev->devfn);
+	dev->irq = pdev->irq;
+
+	DRIVER_PREINIT();
+
+#if __REALLY_HAVE_AGP
+	dev->agp = DRM(agp_init)();
+#if __MUST_HAVE_AGP
+	if ( dev->agp == NULL ) {
+		DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+		DRM(stub_unregister)(dev->minor);
+		DRM(takedown)( dev );
+		return -EINVAL;
+	}
+#endif
+#if __REALLY_HAVE_MTRR
+	if (dev->agp)
+		dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+					dev->agp->agp_info.aper_size*1024*1024,
+					MTRR_TYPE_WRCOMB,
+					1 );
+#endif
 #endif
-	DRM_DEBUG("numdevs = %d\n", num);
-	return num;
+
+#if __HAVE_CTX_BITMAP
+	retcode = DRM(ctxbitmap_init)( dev );
+	if( retcode ) {
+		DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
+		DRM(stub_unregister)(dev->minor);
+		DRM(takedown)( dev );
+		return retcode;
+ 	}
+#endif
+	DRM(numdevs)++; /* no errors, mark it reserved */
+	
+	DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
+		DRIVER_NAME,
+		DRIVER_MAJOR,
+		DRIVER_MINOR,
+		DRIVER_PATCHLEVEL,
+		DRIVER_DATE,
+		dev->minor);
+
+	DRIVER_POSTINIT();
+
+	return 0;
 }
 
 /**
@@ -579,7 +643,7 @@
  *
  * \return zero on success or a negative number on failure.
  *
- * Allocates and initialize an array of drm_device structures, and attempts to
+ * Initializes an array of drm_device structures, and attempts to
  * initialize all available devices, using consecutive minors, registering the
  * stubs and initializing the AGP device.
  * 
@@ -588,88 +652,19 @@
  */
 static int __init drm_init( void )
 {
+	struct pci_dev *pdev = NULL;
 
-	drm_device_t *dev;
-	int i;
-#if __HAVE_CTX_BITMAP
-	int retcode;
-#endif
 	DRM_DEBUG( "\n" );
 
 #ifdef MODULE
 	DRM(parse_options)( drm_opts );
 #endif
 
-	DRM(numdevs) = drm_count_cards();
-	/* Force at least one instance. */
-	if (DRM(numdevs) <= 0)
-		DRM(numdevs) = 1;
-
-	DRM(device) = kmalloc(sizeof(*DRM(device)) * DRM(numdevs), GFP_KERNEL);
-	if (!DRM(device)) {
-		return -ENOMEM;
-	}
-	DRM(minor) = kmalloc(sizeof(*DRM(minor)) * DRM(numdevs), GFP_KERNEL);
-	if (!DRM(minor)) {
-		kfree(DRM(device));
-		return -ENOMEM;
-	}
-
-	DRIVER_PREINIT();
-
 	DRM(mem_init)();
 
-	for (i = 0; i < DRM(numdevs); i++) {
-		dev = &(DRM(device)[i]);
-		memset( (void *)dev, 0, sizeof(*dev) );
-		dev->count_lock = SPIN_LOCK_UNLOCKED;
-		init_timer( &dev->timer );
-		sema_init( &dev->struct_sem, 1 );
-
-		if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
-			return -EPERM;
-		dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
-		dev->name   = DRIVER_NAME;
-
-#if __REALLY_HAVE_AGP
-		dev->agp = DRM(agp_init)();
-#if __MUST_HAVE_AGP
-		if ( dev->agp == NULL ) {
-			DRM_ERROR( "Cannot initialize the agpgart module.\n" );
-			DRM(stub_unregister)(DRM(minor)[i]);
-			DRM(takedown)( dev );
-			return -EINVAL;
-		}
-#endif
-#if __REALLY_HAVE_MTRR
-		if (dev->agp)
-			dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
-				       dev->agp->agp_info.aper_size*1024*1024,
-				       MTRR_TYPE_WRCOMB,
-				       1 );
-#endif
-#endif
-
-#if __HAVE_CTX_BITMAP
-		retcode = DRM(ctxbitmap_init)( dev );
-		if( retcode ) {
-			DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
-			DRM(stub_unregister)(DRM(minor)[i]);
-			DRM(takedown)( dev );
-			return retcode;
-		}
-#endif
-		DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
-		  	DRIVER_NAME,
-		  	DRIVER_MAJOR,
-		  	DRIVER_MINOR,
-		  	DRIVER_PATCHLEVEL,
-		  	DRIVER_DATE,
-		  	DRM(minor)[i] );
+	while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+		DRM(probe)(pdev);
 	}
-
-	DRIVER_POSTINIT();
-
 	return 0;
 }
 
@@ -689,10 +684,10 @@
 
 	for (i = DRM(numdevs) - 1; i >= 0; i--) {
 		dev = &(DRM(device)[i]);
-		if ( DRM(stub_unregister)(DRM(minor)[i]) ) {
+		if ( DRM(stub_unregister)(dev->minor) ) {
 			DRM_ERROR( "Cannot unload module\n" );
 		} else {
-			DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
+			DRM_DEBUG("minor %d unregistered\n", dev->minor);
 			if (i == 0) {
 				DRM_INFO( "Module unloaded\n" );
 			}
@@ -722,8 +717,6 @@
 #endif
 	}
 	DRIVER_POSTCLEANUP();
-	kfree(DRM(minor));
-	kfree(DRM(device));
 	DRM(numdevs) = 0;
 }
 
@@ -795,7 +788,7 @@
 	int i;
 
 	for (i = 0; i < DRM(numdevs); i++) {
-		if (iminor(inode) == DRM(minor)[i]) {
+		if (iminor(inode) == DRM(device)[i].minor) {
 			dev = &(DRM(device)[i]);
 			break;
 		}
@@ -907,6 +900,26 @@
 #endif
 
 	DRM(fasync)( -1, filp, 0 );
+
+	down( &dev->ctxlist_sem );
+	if ( !list_empty( &dev->ctxlist->head ) ) {
+		drm_ctx_list_t *pos, *n;
+
+		list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
+			if ( pos->tag == priv &&
+			     pos->handle != DRM_KERNEL_CONTEXT ) {
+#ifdef DRIVER_CTX_DTOR
+				DRIVER_CTX_DTOR(pos->handle);
+#endif
+#if __HAVE_CTX_BITMAP
+				DRM(ctxbitmap_free)( dev, pos->handle );
+#endif
+				list_del( &pos->head );
+				DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+			}
+		}
+	}
+	up( &dev->ctxlist_sem );
 
 	down( &dev->struct_sem );
 	if ( priv->remove_auth_on_close == 1 ) {
diff -Nru a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h
--- a/drivers/char/drm/drm_fops.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_fops.h	Wed Apr 14 18:25:42 2004
@@ -72,6 +72,8 @@
 	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count    = 0;
 
+	DRIVER_OPEN_HELPER( priv, dev );
+
 	down(&dev->struct_sem);
 	if (!dev->file_last) {
 		priv->next	= NULL;
diff -Nru a/drivers/char/drm/drm_ioctl.h b/drivers/char/drm/drm_ioctl.h
--- a/drivers/char/drm/drm_ioctl.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_ioctl.h	Wed Apr 14 18:25:42 2004
@@ -35,69 +35,7 @@
 
 #include "drmP.h"
 
-
-/**
- * Get interrupt from bus id.
- * 
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_irq_busid structure.
- * \return zero on success or a negative number on failure.
- * 
- * Finds the PCI device with the specified bus id and gets its IRQ number.
- */
-int DRM(irq_busid)(struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg)
-{
-	drm_irq_busid_t p;
-	struct pci_dev	*dev;
-
-	if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
-		return -EFAULT;
-#ifdef __alpha__
-	{
-		int domain = p.busnum >> 8;
-		p.busnum &= 0xff;
-
-		/*
-		 * Find the hose the device is on (the domain number is the
-		 * hose index) and offset the bus by the root bus of that
-		 * hose.
-		 */
-                for(dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
-                    dev;
-                    dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,dev)) {
-			struct pci_controller *hose = dev->sysdata;
-			
-			if (hose->index == domain) {
-				p.busnum += hose->bus->number;
-				break;
-			}
-		}
-	}
-#endif
-	dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
-	if (!dev) {
-		DRM_ERROR("pci_find_slot failed for %d:%d:%d\n",
-			  p.busnum, p.devnum, p.funcnum);
-		p.irq = 0;
-		goto out;
-	}			
-	if (pci_enable_device(dev) != 0) {
-		DRM_ERROR("pci_enable_device failed for %d:%d:%d\n",
-			  p.busnum, p.devnum, p.funcnum);
-		p.irq = 0;
-		goto out;
-	}		
-	p.irq = dev->irq;
- out:
-	DRM_DEBUG("%d:%d:%d => IRQ %d\n",
-		  p.busnum, p.devnum, p.funcnum, p.irq);
-	if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
-		return -EFAULT;
-	return 0;
-}
+#include "linux/pci.h"
 
 /**
  * Get the bus id.
@@ -138,8 +76,10 @@
  * \param arg user argument, pointing to a drm_unique structure.
  * \return zero on success or a negative number on failure.
  *
- * Copies the bus id from userspace into drm_device::unique, and searches for
- * the respective PCI device, updating drm_device::pdev.
+ * Copies the bus id from userspace into drm_device::unique, and verifies that
+ * it matches the device this DRM is attached to (EINVAL otherwise).  Deprecated
+ * in interface version 1.1 and will return EBUSY when setversion has requested
+ * version 1.1 or greater.
  */
 int DRM(setunique)(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
@@ -147,6 +87,7 @@
 	drm_file_t	 *priv	 = filp->private_data;
 	drm_device_t	 *dev	 = priv->dev;
 	drm_unique_t	 u;
+	int		 domain, bus, slot, func, ret;
 
 	if (dev->unique_len || dev->unique) return -EBUSY;
 
@@ -164,55 +105,42 @@
 
 	dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
 				  DRM_MEM_DRIVER);
-	if(!dev->devname) {
-		DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
+	if (!dev->devname)
 		return -ENOMEM;
-	}
+
 	sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
 
-	do {
-		struct pci_dev *pci_dev;
-                int domain, b, d, f;
-                char *p;
- 
-                for(p = dev->unique; p && *p && *p != ':'; p++);
-                if (!p || !*p) break;
-                b = (int)simple_strtoul(p+1, &p, 10);
-                if (*p != ':') break;
-                d = (int)simple_strtoul(p+1, &p, 10);
-                if (*p != ':') break;
-                f = (int)simple_strtoul(p+1, &p, 10);
-                if (*p) break;
- 
-		domain = b >> 8;
-		b &= 0xff;
-
-#ifdef __alpha__
-		/*
-		 * Find the hose the device is on (the domain number is the
-		 * hose index) and offset the bus by the root bus of that
-		 * hose.
-		 */
-                for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
-                    pci_dev;
-                    pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) {
-			struct pci_controller *hose = pci_dev->sysdata;
-			
-			if (hose->index == domain) {
-				b += hose->bus->number;
-				break;
-			}
-		}
-#endif
+	/* Return error if the busid submitted doesn't match the device's actual
+	 * busid.
+	 */
+	ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+	if (ret != 3)
+		return DRM_ERR(EINVAL);
+	domain = bus >> 8;
+	bus &= 0xff;
+	
+	if ((domain != dev->pci_domain) ||
+	    (bus != dev->pci_bus) ||
+	    (slot != dev->pci_slot) ||
+	    (func != dev->pci_func))
+		return -EINVAL;
 
-                pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
-                if (pci_dev) {
-			dev->pdev = pci_dev;
-#ifdef __alpha__
-			dev->hose = pci_dev->sysdata;
-#endif
-		}
-        } while(0);
+	return 0;
+}
+
+static int
+DRM(set_busid)(drm_device_t *dev)
+{
+	if (dev->unique != NULL)
+		return EBUSY;
+
+	dev->unique_len = 20;
+	dev->unique = DRM(alloc)(dev->unique_len + 1, DRM_MEM_DRIVER);
+	if (dev->unique == NULL)
+		return ENOMEM;
+
+	snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+		dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
 
 	return 0;
 }
@@ -361,5 +289,49 @@
 
 	if (copy_to_user((drm_stats_t *)arg, &stats, sizeof(stats)))
 		return -EFAULT;
+	return 0;
+}
+
+#define DRM_IF_MAJOR	1
+#define DRM_IF_MINOR	2
+
+int DRM(setversion)(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_set_version_t sv;
+	drm_set_version_t retv;
+	int if_version;
+
+	DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
+
+	retv.drm_di_major = DRM_IF_MAJOR;
+	retv.drm_di_minor = DRM_IF_MINOR;
+	retv.drm_dd_major = DRIVER_MAJOR;
+	retv.drm_dd_minor = DRIVER_MINOR;
+
+	DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
+
+	if (sv.drm_di_major != -1) {
+		if (sv.drm_di_major != DRM_IF_MAJOR ||
+		    sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
+			return EINVAL;
+		if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
+		dev->if_version = DRM_MAX(if_version, dev->if_version);
+		if (sv.drm_di_minor >= 1) {
+			/*
+			 * Version 1.1 includes tying of DRM to specific device
+			 */
+			DRM(set_busid)(dev);
+		}
+	}
+
+	if (sv.drm_dd_major != -1) {
+		if (sv.drm_dd_major != DRIVER_MAJOR ||
+		    sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
+			return EINVAL;
+#ifdef DRIVER_SETVERSION
+		DRIVER_SETVERSION(dev, &sv);
+#endif
+	}
 	return 0;
 }
diff -Nru a/drivers/char/drm/drm_irq.h b/drivers/char/drm/drm_irq.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/drm/drm_irq.h	Wed Apr 14 18:25:42 2004
@@ -0,0 +1,372 @@
+/**
+ * \file drm_irq.h 
+ * IRQ support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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, sublicense,
+ * 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 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.
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#include <linux/interrupt.h>	/* For task queue support */
+
+#ifndef __HAVE_SHARED_IRQ
+#define __HAVE_SHARED_IRQ	0
+#endif
+
+#if __HAVE_SHARED_IRQ
+#define DRM_IRQ_TYPE		SA_SHIRQ
+#else
+#define DRM_IRQ_TYPE		0
+#endif
+
+/**
+ * Get interrupt from bus id.
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_irq_busid structure.
+ * \return zero on success or a negative number on failure.
+ * 
+ * Finds the PCI device with the specified bus id and gets its IRQ number.
+ * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
+ * to that of the device that this DRM instance attached to.
+ */
+int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
+		   unsigned int cmd, unsigned long arg)
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_irq_busid_t p;
+
+	if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
+		return -EFAULT;
+
+	if ((p.busnum >> 8) != dev->pci_domain ||
+	    (p.busnum & 0xff) != dev->pci_bus ||
+	    p.devnum != dev->pci_slot ||
+	    p.funcnum != dev->pci_func)
+		return -EINVAL;
+
+	p.irq = dev->irq;
+
+	DRM_DEBUG("%d:%d:%d => IRQ %d\n",
+		  p.busnum, p.devnum, p.funcnum, p.irq);
+	if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
+		return -EFAULT;
+	return 0;
+}
+
+#if __HAVE_IRQ
+
+/**
+ * Install IRQ handler.
+ *
+ * \param dev DRM device.
+ * \param irq IRQ number.
+ *
+ * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
+ * \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions
+ * before and after the installation.
+ */
+int DRM(irq_install)( drm_device_t *dev )
+{
+	int ret;
+ 
+	if ( dev->irq == 0 )
+		return -EINVAL;
+
+	down( &dev->struct_sem );
+
+	/* Driver must have been initialized */
+	if ( !dev->dev_private ) {
+		up( &dev->struct_sem );
+		return -EINVAL;
+	}
+
+	if ( dev->irq_enabled ) {
+		up( &dev->struct_sem );
+		return -EBUSY;
+	}
+	dev->irq_enabled = 1;
+	up( &dev->struct_sem );
+
+	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
+
+#if __HAVE_DMA
+	dev->dma->next_buffer = NULL;
+	dev->dma->next_queue = NULL;
+	dev->dma->this_buffer = NULL;
+#endif
+
+#if __HAVE_IRQ_BH
+	INIT_WORK(&dev->work, DRM(irq_immediate_bh), dev);
+#endif
+
+#if __HAVE_VBL_IRQ
+	init_waitqueue_head(&dev->vbl_queue);
+
+	spin_lock_init( &dev->vbl_lock );
+
+	INIT_LIST_HEAD( &dev->vbl_sigs.head );
+
+	dev->vbl_pending = 0;
+#endif
+
+				/* Before installing handler */
+	DRM(driver_irq_preinstall)(dev);
+
+				/* Install handler */
+	ret = request_irq( dev->irq, DRM(irq_handler),
+			   DRM_IRQ_TYPE, dev->devname, dev );
+	if ( ret < 0 ) {
+		down( &dev->struct_sem );
+		dev->irq_enabled = 0;
+		up( &dev->struct_sem );
+		return ret;
+	}
+
+				/* After installing handler */
+	DRM(driver_irq_postinstall)(dev);
+
+	return 0;
+}
+
+/**
+ * Uninstall the IRQ handler.
+ *
+ * \param dev DRM device.
+ *
+ * Calls the driver's \c DRM(driver_irq_uninstall)() function, and stops the irq.
+ */
+int DRM(irq_uninstall)( drm_device_t *dev )
+{
+	int irq_enabled;
+
+	down( &dev->struct_sem );
+	irq_enabled = dev->irq_enabled;
+	dev->irq_enabled = 0;
+	up( &dev->struct_sem );
+
+	if ( !irq_enabled )
+		return -EINVAL;
+
+	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
+
+	DRM(driver_irq_uninstall)( dev );
+
+	free_irq( dev->irq, dev );
+
+	return 0;
+}
+
+/**
+ * IRQ control ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_control structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls irq_install() or irq_uninstall() according to \p arg.
+ */
+int DRM(control)( struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_control_t ctl;
+
+	if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
+		return -EFAULT;
+
+	switch ( ctl.func ) {
+	case DRM_INST_HANDLER:
+		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
+		    ctl.irq != dev->irq)
+			return -EINVAL;
+		return DRM(irq_install)( dev );
+	case DRM_UNINST_HANDLER:
+		return DRM(irq_uninstall)( dev );
+	default:
+		return -EINVAL;
+	}
+}
+
+#if __HAVE_VBL_IRQ
+
+/**
+ * Wait for VBLANK.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param data user argument, pointing to a drm_wait_vblank structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the IRQ is installed. 
+ *
+ * If a signal is requested checks if this task has already scheduled the same signal
+ * for the same vblank sequence number - nothing to be done in
+ * that case. If the number of tasks waiting for the interrupt exceeds 100 the
+ * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
+ * task.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+int DRM(wait_vblank)( DRM_IOCTL_ARGS )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_wait_vblank_t vblwait;
+	struct timeval now;
+	int ret = 0;
+	unsigned int flags;
+
+	if (!dev->irq)
+		return -EINVAL;
+
+	DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
+				  sizeof(vblwait) );
+
+	switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
+	case _DRM_VBLANK_RELATIVE:
+		vblwait.request.sequence += atomic_read( &dev->vbl_received );
+		vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+	case _DRM_VBLANK_ABSOLUTE:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+	
+	if ( flags & _DRM_VBLANK_SIGNAL ) {
+		unsigned long irqflags;
+		drm_vbl_sig_t *vbl_sig;
+		
+		vblwait.reply.sequence = atomic_read( &dev->vbl_received );
+
+		spin_lock_irqsave( &dev->vbl_lock, irqflags );
+
+		/* Check if this task has already scheduled the same signal
+		 * for the same vblank sequence number; nothing to be done in
+		 * that case
+		 */
+		list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
+			if (vbl_sig->sequence == vblwait.request.sequence
+			    && vbl_sig->info.si_signo == vblwait.request.signal
+			    && vbl_sig->task == current)
+			{
+				spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+				goto done;
+			}
+		}
+
+		if ( dev->vbl_pending >= 100 ) {
+			spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+			return -EBUSY;
+		}
+
+		dev->vbl_pending++;
+
+		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+
+		if ( !( vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) ) ) ) {
+			return -ENOMEM;
+		}
+
+		memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
+
+		vbl_sig->sequence = vblwait.request.sequence;
+		vbl_sig->info.si_signo = vblwait.request.signal;
+		vbl_sig->task = current;
+
+		spin_lock_irqsave( &dev->vbl_lock, irqflags );
+
+		list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
+
+		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+	} else {
+		ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
+
+		do_gettimeofday( &now );
+		vblwait.reply.tval_sec = now.tv_sec;
+		vblwait.reply.tval_usec = now.tv_usec;
+	}
+
+done:
+	DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
+				sizeof(vblwait) );
+
+	return ret;
+}
+
+/**
+ * Send the VBLANK signals.
+ *
+ * \param dev DRM device.
+ *
+ * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+void DRM(vbl_send_signals)( drm_device_t *dev )
+{
+	struct list_head *list, *tmp;
+	drm_vbl_sig_t *vbl_sig;
+	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
+	unsigned long flags;
+
+	spin_lock_irqsave( &dev->vbl_lock, flags );
+
+	list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
+		vbl_sig = list_entry( list, drm_vbl_sig_t, head );
+		if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
+			vbl_sig->info.si_code = vbl_seq;
+			send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
+
+			list_del( list );
+
+			DRM_FREE( vbl_sig, sizeof(*vbl_sig) );
+
+			dev->vbl_pending--;
+		}
+	}
+
+	spin_unlock_irqrestore( &dev->vbl_lock, flags );
+}
+
+#endif	/* __HAVE_VBL_IRQ */
+
+#endif /* __HAVE_IRQ */
diff -Nru a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
--- a/drivers/char/drm/drm_memory_debug.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_memory_debug.h	Wed Apr 14 18:25:42 2004
@@ -67,6 +67,7 @@
 	[DRM_MEM_TOTALAGP]  = { "totalagp" },
 	[DRM_MEM_BOUNDAGP]  = { "boundagp" },
 	[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
+	[DRM_MEM_CTXLIST]   = { "ctxlist"  },
 	[DRM_MEM_STUB]      = { "stub"     },
 	{ NULL, 0, }		/* Last entry must be null */
 };
diff -Nru a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
--- a/drivers/char/drm/drm_os_linux.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_os_linux.h	Wed Apr 14 18:25:42 2004
@@ -62,14 +62,20 @@
 	verify_area( VERIFY_READ, uaddr, size )
 #define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) 	\
 	__copy_from_user(arg1, arg2, arg3)
+#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3)	\
+	__copy_to_user(arg1, arg2, arg3)
 #define DRM_GET_USER_UNCHECKED(val, uaddr)		\
 	__get_user(val, uaddr)
+#define DRM_PUT_USER_UNCHECKED(uaddr, val)		\
+	__put_user(val, uaddr)
 
 
 /** 'malloc' without the overhead of DRM(alloc)() */
 #define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL)
 /** 'free' without the overhead of DRM(free)() */
 #define DRM_FREE(x,size) kfree(x)
+
+#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
 
 /** 
  * Get the pointer to the SAREA.
diff -Nru a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
--- a/drivers/char/drm/drm_sarea.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_sarea.h	Wed Apr 14 18:25:42 2004
@@ -32,8 +32,22 @@
 #ifndef _DRM_SAREA_H_
 #define _DRM_SAREA_H_
 
+#include "drm.h"
+
+/* SAREA area needs to be at least a page */
+#if defined(__alpha__)
+#define SAREA_MAX                       0x2000
+#elif defined(__ia64__)
+#define SAREA_MAX                       0x10000         /* 64kB */
+#else
+/* Intel 830M driver needs at least 8k SAREA */
+#define SAREA_MAX                       0x2000
+#endif
+
 /** Maximum number of drawables in the SAREA */
 #define SAREA_MAX_DRAWABLES 		256
+
+#define SAREA_DRAWABLE_CLAIMED_ENTRY    0x80000000
 
 /** SAREA drawable */
 typedef struct drm_sarea_drawable {
diff -Nru a/drivers/char/drm/drm_stub.h b/drivers/char/drm/drm_stub.h
--- a/drivers/char/drm/drm_stub.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_stub.h	Wed Apr 14 18:25:42 2004
@@ -209,8 +209,8 @@
 		ret2 = DRM(stub_info).info_register(name, fops, dev);
 		if (ret2) {
 			if (!ret1) {
-			unregister_chrdev(DRM_MAJOR, "drm");
-			class_simple_destroy(drm_class);
+				unregister_chrdev(DRM_MAJOR, "drm");
+				class_simple_destroy(drm_class);
 			}
 			if (!i)
 				inter_module_unregister("drm");
diff -Nru a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h
--- a/drivers/char/drm/drm_vm.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/drm_vm.h	Wed Apr 14 18:25:42 2004
@@ -35,48 +35,19 @@
 
 #include "drmP.h"
 
-/** AGP virtual memory operations */
-struct vm_operations_struct   DRM(vm_ops) = {
-	.nopage = DRM(vm_nopage),
-	.open	= DRM(vm_open),
-	.close	= DRM(vm_close),
-};
-
-/** Shared virtual memory operations */
-struct vm_operations_struct   DRM(vm_shm_ops) = {
-	.nopage = DRM(vm_shm_nopage),
-	.open	= DRM(vm_open),
-	.close	= DRM(vm_shm_close),
-};
-
-/** DMA virtual memory operations */
-struct vm_operations_struct   DRM(vm_dma_ops) = {
-	.nopage = DRM(vm_dma_nopage),
-	.open	= DRM(vm_open),
-	.close	= DRM(vm_close),
-};
-
-/** Scatter-gather virtual memory operations */
-struct vm_operations_struct   DRM(vm_sg_ops) = {
-	.nopage = DRM(vm_sg_nopage),
-	.open   = DRM(vm_open),
-	.close  = DRM(vm_close),
-};
 
 /**
  * \c nopage method for AGP virtual memory.
  *
  * \param vma virtual memory area.
  * \param address access address.
- * \param write_access sharing.
  * \return pointer to the page structure.
  * 
  * Find the right map and if it's AGP memory find the real physical page to
  * map, get the page, increment the use count and return it.
  */
-struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
-			    unsigned long address,
-			    int *type)
+static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma,
+						 unsigned long address)
 {
 #if __REALLY_HAVE_AGP
 	drm_file_t *priv  = vma->vm_file->private_data;
@@ -133,8 +104,6 @@
 			  baddr, __va(agpmem->memory->memory[offset]), offset,
 			  atomic_read(&page->count));
 
-		if (type)
-			*type = VM_FAULT_MINOR;
 		return page;
         }
 vm_nopage_error:
@@ -148,15 +117,13 @@
  *
  * \param vma virtual memory area.
  * \param address access address.
- * \param write_access sharing.
  * \return pointer to the page structure.
  * 
  * Get the the mapping, find the real physical page to map, get the page, and
  * return it.
  */
-struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
-				unsigned long address,
-				int *type)
+static __inline__ struct page *DRM(do_vm_shm_nopage)(struct vm_area_struct *vma,
+						     unsigned long address)
 {
 	drm_map_t	 *map	 = (drm_map_t *)vma->vm_private_data;
 	unsigned long	 offset;
@@ -172,8 +139,6 @@
 	if (!page)
 		return NOPAGE_OOM;
 	get_page(page);
-	if (type)
-		*type = VM_FAULT_MINOR;
 
 	DRM_DEBUG("shm_nopage 0x%lx\n", address);
 	return page;
@@ -265,14 +230,12 @@
  *
  * \param vma virtual memory area.
  * \param address access address.
- * \param write_access sharing.
  * \return pointer to the page structure.
  * 
  * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
  */
-struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
-				unsigned long address,
-				int *type)
+static __inline__ struct page *DRM(do_vm_dma_nopage)(struct vm_area_struct *vma,
+						     unsigned long address)
 {
 	drm_file_t	 *priv	 = vma->vm_file->private_data;
 	drm_device_t	 *dev	 = priv->dev;
@@ -291,8 +254,6 @@
 			     (offset & (~PAGE_MASK))));
 
 	get_page(page);
-	if (type)
-		*type = VM_FAULT_MINOR;
 
 	DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr);
 	return page;
@@ -303,14 +264,12 @@
  *
  * \param vma virtual memory area.
  * \param address access address.
- * \param write_access sharing.
  * \return pointer to the page structure.
  * 
  * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
  */
-struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
-			       unsigned long address,
-			       int *type)
+static __inline__ struct page *DRM(do_vm_sg_nopage)(struct vm_area_struct *vma,
+						    unsigned long address)
 {
 	drm_map_t        *map    = (drm_map_t *)vma->vm_private_data;
 	drm_file_t *priv = vma->vm_file->private_data;
@@ -331,11 +290,98 @@
 	page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
 	page = entry->pagelist[page_offset];
 	get_page(page);
-	if (type)
-		*type = VM_FAULT_MINOR;
 
 	return page;
 }
+
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+
+static struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
+				   unsigned long address,
+				   int *type) {
+	if (type) *type = VM_FAULT_MINOR;
+	return DRM(do_vm_nopage)(vma, address);
+}
+
+static struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
+				       unsigned long address,
+				       int *type) {
+	if (type) *type = VM_FAULT_MINOR;
+	return DRM(do_vm_shm_nopage)(vma, address);
+}
+
+static struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
+				       unsigned long address,
+				       int *type) {
+	if (type) *type = VM_FAULT_MINOR;
+	return DRM(do_vm_dma_nopage)(vma, address);
+}
+
+static struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+				      unsigned long address,
+				      int *type) {
+	if (type) *type = VM_FAULT_MINOR;
+	return DRM(do_vm_sg_nopage)(vma, address);
+}
+
+#else	/* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */
+
+static struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
+				   unsigned long address,
+				   int unused) {
+	return DRM(do_vm_nopage)(vma, address);
+}
+
+static struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
+				       unsigned long address,
+				       int unused) {
+	return DRM(do_vm_shm_nopage)(vma, address);
+}
+
+static struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
+				       unsigned long address,
+				       int unused) {
+	return DRM(do_vm_dma_nopage)(vma, address);
+}
+
+static struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+				      unsigned long address,
+				      int unused) {
+	return DRM(do_vm_sg_nopage)(vma, address);
+}
+
+#endif
+
+
+/** AGP virtual memory operations */
+static struct vm_operations_struct   DRM(vm_ops) = {
+	.nopage = DRM(vm_nopage),
+	.open	= DRM(vm_open),
+	.close	= DRM(vm_close),
+};
+
+/** Shared virtual memory operations */
+static struct vm_operations_struct   DRM(vm_shm_ops) = {
+	.nopage = DRM(vm_shm_nopage),
+	.open	= DRM(vm_open),
+	.close	= DRM(vm_shm_close),
+};
+
+/** DMA virtual memory operations */
+static struct vm_operations_struct   DRM(vm_dma_ops) = {
+	.nopage = DRM(vm_dma_nopage),
+	.open	= DRM(vm_open),
+	.close	= DRM(vm_close),
+};
+
+/** Scatter-gather virtual memory operations */
+static struct vm_operations_struct   DRM(vm_sg_ops) = {
+	.nopage = DRM(vm_sg_nopage),
+	.open   = DRM(vm_open),
+	.close  = DRM(vm_close),
+};
+
 
 /**
  * \c open method for shared virtual memory.
diff -Nru a/drivers/char/drm/gamma.h b/drivers/char/drm/gamma.h
--- a/drivers/char/drm/gamma.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/gamma.h	Wed Apr 14 18:25:42 2004
@@ -53,6 +53,10 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_GAMMA_INIT)] = { gamma_dma_init,  1, 1 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_GAMMA_COPY)] = { gamma_dma_copy,  1, 1 }
 
+#define DRIVER_PCI_IDS							\
+	{0x3d3d, 0x0008, 0},			\
+	{0, 0, 0}
+
 #define IOCTL_TABLE_NAME	DRM(ioctls)
 #define IOCTL_FUNC_NAME 	DRM(ioctl)
 
@@ -104,8 +108,8 @@
 	return 0;							\
 } while (0)
 
-#define __HAVE_DMA_IRQ			1
-#define __HAVE_DMA_IRQ_BH		1
+#define __HAVE_IRQ			1
+#define __HAVE_IRQ_BH			1
 
 #define DRIVER_AGP_BUFFERS_MAP( dev )					\
 	((drm_gamma_private_t *)((dev)->dev_private))->buffers
diff -Nru a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c
--- a/drivers/char/drm/gamma_dma.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/gamma_dma.c	Wed Apr 14 18:25:42 2004
@@ -116,7 +116,7 @@
 	return (!GAMMA_READ(GAMMA_DMACOUNT));
 }
 
-irqreturn_t gamma_dma_service( DRM_IRQ_ARGS )
+irqreturn_t gamma_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t	 *dev = (drm_device_t *)arg;
 	drm_device_dma_t *dma = dev->dma;
@@ -262,7 +262,7 @@
 	gamma_dma_schedule((drm_device_t *)dev, 0);
 }
 
-void gamma_dma_immediate_bh(void *dev)
+void gamma_irq_immediate_bh(void *dev)
 {
 	gamma_dma_schedule(dev, 0);
 }
@@ -656,12 +656,12 @@
 {
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq ) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if ( dev->dev_private ) {
diff -Nru a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c
--- a/drivers/char/drm/gamma_drv.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/gamma_drv.c	Wed Apr 14 18:25:42 2004
@@ -48,6 +48,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "gamma_lists.h"        /* NOTE */
 #include "drm_lock.h"
 #include "gamma_lock.h"		/* NOTE */
diff -Nru a/drivers/char/drm/i810.h b/drivers/char/drm/i810.h
--- a/drivers/char/drm/i810.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/i810.h	Wed Apr 14 18:25:42 2004
@@ -77,7 +77,14 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_MC)]      = { i810_dma_mc,     1, 1 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_FLIP)] =    { i810_flip_bufs,  1, 0 }
- 
+
+#define DRIVER_PCI_IDS							\
+	{0x8086, 0x7121, 0},						\
+	{0x8086, 0x7123, 0},						\
+	{0x8086, 0x7125, 0},						\
+	{0x8086, 0x1132, 0},						\
+	{0, 0, 0}
+
 
 #define __HAVE_COUNTERS         4
 #define __HAVE_COUNTER6         _DRM_STAT_IRQ
@@ -112,7 +119,7 @@
  * a noop stub is generated for compatibility.
  */
 /* XXX: Add vblank support? */
-#define __HAVE_DMA_IRQ		0
+#define __HAVE_IRQ		0
 
 /* Buffer customization:
  */
diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
--- a/drivers/char/drm/i810_dma.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/i810_dma.c	Wed Apr 14 18:25:42 2004
@@ -232,12 +232,12 @@
 {
 	drm_device_dma_t *dma = dev->dma;
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if (dev->irq) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if (dev->dev_private) {
diff -Nru a/drivers/char/drm/i830.h b/drivers/char/drm/i830.h
--- a/drivers/char/drm/i830.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/i830.h	Wed Apr 14 18:25:42 2004
@@ -77,6 +77,13 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam,  1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam,  1, 0 } 
 
+#define DRIVER_PCI_IDS							\
+	{0x8086, 0x3577, 0},						\
+	{0x8086, 0x2562, 0},						\
+	{0x8086, 0x3582, 0},						\
+ 	{0x8086, 0x2572, 0},				 		\
+	{0, 0, 0}
+
 #define __HAVE_COUNTERS         4
 #define __HAVE_COUNTER6         _DRM_STAT_IRQ
 #define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
@@ -115,10 +122,10 @@
 #define USE_IRQS 0
 
 #if USE_IRQS
-#define __HAVE_DMA_IRQ		1
+#define __HAVE_IRQ		1
 #define __HAVE_SHARED_IRQ	1
 #else
-#define __HAVE_DMA_IRQ          0
+#define __HAVE_IRQ          0
 #endif
 
 
diff -Nru a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
--- a/drivers/char/drm/i830_dma.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/i830_dma.c	Wed Apr 14 18:25:42 2004
@@ -232,12 +232,12 @@
 {
 	drm_device_dma_t *dma = dev->dma;
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if (dev->irq) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if (dev->dev_private) {
@@ -1540,7 +1540,7 @@
 
 	switch( param.param ) {
 	case I830_PARAM_IRQ_ACTIVE:
-		value = dev->irq ? 1 : 0;
+		value = dev->irq_enabled;
 		break;
 	default:
 		return -EINVAL;
diff -Nru a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
--- a/drivers/char/drm/i830_drv.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/i830_drv.c	Wed Apr 14 18:25:42 2004
@@ -50,6 +50,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "drm_lock.h"
 #include "drm_memory.h"
 #include "drm_proc.h"
diff -Nru a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
--- a/drivers/char/drm/i830_irq.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/i830_irq.c	Wed Apr 14 18:25:42 2004
@@ -35,7 +35,7 @@
 #include <linux/delay.h>
 
 
-irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS )
+irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS )
 {
 	drm_device_t	 *dev = (drm_device_t *)arg;
       	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
diff -Nru a/drivers/char/drm/mga.h b/drivers/char/drm/mga.h
--- a/drivers/char/drm/mga.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/mga.h	Wed Apr 14 18:25:42 2004
@@ -64,6 +64,12 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam,    1, 0 },
 
+#define DRIVER_PCI_IDS							\
+	{0x102b, 0x0521, 0},						\
+	{0x102b, 0x0525, 0},						\
+	{0x102b, 0x2527, 0},						\
+	{0, 0, 0}
+
 #define __HAVE_COUNTERS         3
 #define __HAVE_COUNTER6         _DRM_STAT_IRQ
 #define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
@@ -78,7 +84,7 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
-#define __HAVE_DMA_IRQ		1
+#define __HAVE_IRQ		1
 #define __HAVE_VBL_IRQ		1
 #define __HAVE_SHARED_IRQ       1
 
diff -Nru a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
--- a/drivers/char/drm/mga_dma.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/mga_dma.c	Wed Apr 14 18:25:42 2004
@@ -500,14 +500,6 @@
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
-	if(!dev_priv->fb) {
-		DRM_ERROR( "failed to find framebuffer!\n" );
-		/* Assign dev_private so we can do cleanup. */
-		dev->dev_private = (void *)dev_priv;
-		mga_do_cleanup_dma( dev );
-		return DRM_ERR(EINVAL);
-	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
 		DRM_ERROR( "failed to find mmio region!\n" );
@@ -639,12 +631,12 @@
 {
 	DRM_DEBUG( "\n" );
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq ) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if ( dev->dev_private ) {
diff -Nru a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
--- a/drivers/char/drm/mga_drm.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/mga_drm.h	Wed Apr 14 18:25:42 2004
@@ -117,6 +117,8 @@
 #define MGA_NR_TEX_REGIONS		16
 #define MGA_LOG_MIN_TEX_REGION_SIZE	16
 
+#define  DRM_MGA_IDLE_RETRY          2048
+
 #endif /* __MGA_SAREA_DEFINES__ */
 
 
@@ -230,16 +232,27 @@
 /* MGA specific ioctls
  * The device specific ioctl range is 0x40 to 0x79.
  */
-#define DRM_IOCTL_MGA_INIT		DRM_IOW( 0x40, drm_mga_init_t)
-#define DRM_IOCTL_MGA_FLUSH		DRM_IOW( 0x41, drm_lock_t)
-#define DRM_IOCTL_MGA_RESET		DRM_IO(  0x42)
-#define DRM_IOCTL_MGA_SWAP		DRM_IO(  0x43)
-#define DRM_IOCTL_MGA_CLEAR		DRM_IOW( 0x44, drm_mga_clear_t)
-#define DRM_IOCTL_MGA_VERTEX		DRM_IOW( 0x45, drm_mga_vertex_t)
-#define DRM_IOCTL_MGA_INDICES		DRM_IOW( 0x46, drm_mga_indices_t)
-#define DRM_IOCTL_MGA_ILOAD		DRM_IOW( 0x47, drm_mga_iload_t)
-#define DRM_IOCTL_MGA_BLIT		DRM_IOW( 0x48, drm_mga_blit_t)
-#define DRM_IOCTL_MGA_GETPARAM		DRM_IOWR(0x49, drm_mga_getparam_t)
+#define DRM_MGA_INIT     0x00
+#define DRM_MGA_FLUSH    0x01
+#define DRM_MGA_RESET    0x02
+#define DRM_MGA_SWAP     0x03
+#define DRM_MGA_CLEAR    0x04
+#define DRM_MGA_VERTEX   0x05
+#define DRM_MGA_INDICES  0x06
+#define DRM_MGA_ILOAD    0x07
+#define DRM_MGA_BLIT     0x08
+#define DRM_MGA_GETPARAM 0x09
+
+#define DRM_IOCTL_MGA_INIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
+#define DRM_IOCTL_MGA_FLUSH    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
+#define DRM_IOCTL_MGA_RESET    DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_RESET)
+#define DRM_IOCTL_MGA_SWAP     DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_SWAP)
+#define DRM_IOCTL_MGA_CLEAR    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t)
+#define DRM_IOCTL_MGA_VERTEX   DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t)
+#define DRM_IOCTL_MGA_INDICES  DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t)
+#define DRM_IOCTL_MGA_ILOAD    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t)
+#define DRM_IOCTL_MGA_BLIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t)
+#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t)
 
 typedef struct _drm_mga_warp_index {
    	int installed;
@@ -330,7 +343,7 @@
 
 typedef struct drm_mga_getparam {
 	int param;
-	int *value;
+	void *value;
 } drm_mga_getparam_t;
 
 #endif
diff -Nru a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
--- a/drivers/char/drm/mga_drv.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/mga_drv.c	Wed Apr 14 18:25:42 2004
@@ -45,6 +45,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "drm_lock.h"
 #include "drm_memory.h"
 #include "drm_proc.h"
diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
--- a/drivers/char/drm/mga_drv.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/mga_drv.h	Wed Apr 14 18:25:42 2004
@@ -91,7 +91,6 @@
 	unsigned int texture_size;
 
 	drm_local_map_t *sarea;
-	drm_local_map_t *fb;
 	drm_local_map_t *mmio;
 	drm_local_map_t *status;
 	drm_local_map_t *warp;
diff -Nru a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
--- a/drivers/char/drm/mga_irq.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/mga_irq.c	Wed Apr 14 18:25:42 2004
@@ -36,7 +36,7 @@
 #include "mga_drm.h"
 #include "mga_drv.h"
 
-irqreturn_t mga_dma_service( DRM_IRQ_ARGS )
+irqreturn_t mga_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_mga_private_t *dev_priv = 
diff -Nru a/drivers/char/drm/r128.h b/drivers/char/drm/r128.h
--- a/drivers/char/drm/r128.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/r128.h	Wed Apr 14 18:25:42 2004
@@ -79,6 +79,46 @@
    [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 }, \
    [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)]   = { r128_getparam, 1, 0 },
 
+#define DRIVER_PCI_IDS							\
+	{0x1002, 0x4c45, 0},						\
+	{0x1002, 0x4c46, 0},						\
+	{0x1002, 0x4d46, 0},						\
+	{0x1002, 0x4d4c, 0},						\
+	{0x1002, 0x5041, 0},						\
+	{0x1002, 0x5042, 0},						\
+	{0x1002, 0x5043, 0},						\
+	{0x1002, 0x5044, 0},						\
+	{0x1002, 0x5045, 0},						\
+	{0x1002, 0x5046, 0},						\
+	{0x1002, 0x5047, 0},						\
+	{0x1002, 0x5048, 0},						\
+	{0x1002, 0x5049, 0},						\
+	{0x1002, 0x504A, 0},						\
+	{0x1002, 0x504B, 0},						\
+	{0x1002, 0x504C, 0},						\
+	{0x1002, 0x504D, 0},						\
+	{0x1002, 0x504E, 0},						\
+	{0x1002, 0x504F, 0},						\
+	{0x1002, 0x5050, 0},						\
+	{0x1002, 0x5051, 0},						\
+	{0x1002, 0x5052, 0},						\
+	{0x1002, 0x5053, 0},						\
+	{0x1002, 0x5054, 0},						\
+	{0x1002, 0x5055, 0},						\
+	{0x1002, 0x5056, 0},						\
+	{0x1002, 0x5057, 0},						\
+	{0x1002, 0x5058, 0},						\
+	{0x1002, 0x5245, 0},						\
+	{0x1002, 0x5246, 0},						\
+	{0x1002, 0x5247, 0},						\
+	{0x1002, 0x524b, 0},						\
+	{0x1002, 0x524c, 0},						\
+	{0x1002, 0x534d, 0},						\
+	{0x1002, 0x5446, 0},						\
+	{0x1002, 0x544C, 0},						\
+	{0x1002, 0x5452, 0},						\
+	{0, 0, 0}
+
 /* Driver customization:
  */
 #define DRIVER_PRERELEASE() do {					\
@@ -97,7 +137,7 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
-#define __HAVE_DMA_IRQ		1
+#define __HAVE_IRQ		1
 #define __HAVE_VBL_IRQ		1
 #define __HAVE_SHARED_IRQ       1
 
diff -Nru a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
--- a/drivers/char/drm/r128_cce.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/r128_cce.c	Wed Apr 14 18:25:42 2004
@@ -212,7 +212,7 @@
 	int i;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		if ( GET_RING_HEAD( &dev_priv->ring ) == dev_priv->ring.tail ) {
+		if ( GET_RING_HEAD( dev_priv ) == dev_priv->ring.tail ) {
 			int pm4stat = R128_READ( R128_PM4_STAT );
 			if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
 			       dev_priv->cce_fifo_size ) &&
@@ -238,7 +238,8 @@
 	r128_do_wait_for_idle( dev_priv );
 
 	R128_WRITE( R128_PM4_BUFFER_CNTL,
-		    dev_priv->cce_mode | dev_priv->ring.size_l2qw );
+		    dev_priv->cce_mode | dev_priv->ring.size_l2qw
+		    | R128_PM4_BUFFER_CNTL_NOUPDATE );
 	R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
 	R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
 
@@ -253,7 +254,6 @@
 {
 	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
 	R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
-	SET_RING_HEAD( &dev_priv->ring, 0 );
 	dev_priv->ring.tail = 0;
 }
 
@@ -264,7 +264,8 @@
 static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
 {
 	R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
-	R128_WRITE( R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4 );
+	R128_WRITE( R128_PM4_BUFFER_CNTL,
+		    R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE );
 
 	dev_priv->cce_running = 0;
 }
@@ -333,26 +334,6 @@
 	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
 	R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
 
-	/* DL_RPTR_ADDR is a physical address in AGP space. */
-	SET_RING_HEAD( &dev_priv->ring, 0 );
-
-	if ( !dev_priv->is_pci ) {
-		R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
-			    dev_priv->ring_rptr->offset );
-	} else {
-		drm_sg_mem_t *entry = dev->sg;
-		unsigned long tmp_ofs, page_ofs;
-
-		tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
-		page_ofs = tmp_ofs >> PAGE_SHIFT;
-
-		R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
-     			    entry->busaddr[page_ofs]);
-		DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
-			   (unsigned long) entry->busaddr[page_ofs],
-     			   entry->handle + tmp_ofs );
-	}
-
 	/* Set watermark control */
 	R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
 		    ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
@@ -486,13 +467,6 @@
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
-	if(!dev_priv->fb) {
-		DRM_ERROR("could not find framebuffer!\n");
-		dev->dev_private = (void *)dev_priv;
-		r128_do_cleanup_cce( dev );
-		return DRM_ERR(EINVAL);
-	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
@@ -567,9 +541,6 @@
 #endif
 		dev_priv->cce_buffers_offset = dev->sg->handle;
 
-	dev_priv->ring.head = ((__volatile__ u32 *)
-			       dev_priv->ring_rptr->handle);
-
 	dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle;
 	dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
 			      + init->ring_size / sizeof(u32));
@@ -580,7 +551,6 @@
 		(dev_priv->ring.size / sizeof(u32)) - 1;
 
 	dev_priv->ring.high_mark = 128;
-	dev_priv->ring.ring_rptr = dev_priv->ring_rptr;
 
 	dev_priv->sarea_priv->last_frame = 0;
 	R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame );
@@ -589,8 +559,9 @@
 	R128_WRITE( R128_LAST_DISPATCH_REG,
 		    dev_priv->sarea_priv->last_dispatch );
 
-#if __REALLY_HAVE_SG
+#if __REALLY_HAVE_AGP
 	if ( dev_priv->is_pci ) {
+#endif
 		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
      					    &dev_priv->bus_pci_gart) ) {
 			DRM_ERROR( "failed to init PCI GART!\n" );
@@ -599,6 +570,7 @@
 			return DRM_ERR(ENOMEM);
 		}
 		R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
+#if __REALLY_HAVE_AGP
 	}
 #endif
 
@@ -615,12 +587,12 @@
 int r128_do_cleanup_cce( drm_device_t *dev )
 {
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq ) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if ( dev->dev_private ) {
@@ -901,7 +873,7 @@
 	int i;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		r128_update_ring_snapshot( ring );
+		r128_update_ring_snapshot( dev_priv );
 		if ( ring->space >= n )
 			return 0;
 		DRM_UDELAY( 1 );
diff -Nru a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
--- a/drivers/char/drm/r128_drm.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/r128_drm.h	Wed Apr 14 18:25:42 2004
@@ -176,24 +176,47 @@
 /* Rage 128 specific ioctls
  * The device specific ioctl range is 0x40 to 0x79.
  */
-#define DRM_IOCTL_R128_INIT		DRM_IOW( 0x40, drm_r128_init_t)
-#define DRM_IOCTL_R128_CCE_START	DRM_IO(  0x41)
-#define DRM_IOCTL_R128_CCE_STOP		DRM_IOW( 0x42, drm_r128_cce_stop_t)
-#define DRM_IOCTL_R128_CCE_RESET	DRM_IO(  0x43)
-#define DRM_IOCTL_R128_CCE_IDLE		DRM_IO(  0x44)
-#define DRM_IOCTL_R128_RESET		DRM_IO(  0x46)
-#define DRM_IOCTL_R128_SWAP		DRM_IO(  0x47)
-#define DRM_IOCTL_R128_CLEAR		DRM_IOW( 0x48, drm_r128_clear_t)
-#define DRM_IOCTL_R128_VERTEX		DRM_IOW( 0x49, drm_r128_vertex_t)
-#define DRM_IOCTL_R128_INDICES		DRM_IOW( 0x4a, drm_r128_indices_t)
-#define DRM_IOCTL_R128_BLIT		DRM_IOW( 0x4b, drm_r128_blit_t)
-#define DRM_IOCTL_R128_DEPTH		DRM_IOW( 0x4c, drm_r128_depth_t)
-#define DRM_IOCTL_R128_STIPPLE		DRM_IOW( 0x4d, drm_r128_stipple_t)
-#define DRM_IOCTL_R128_INDIRECT		DRM_IOWR(0x4f, drm_r128_indirect_t)
-#define DRM_IOCTL_R128_FULLSCREEN	DRM_IOW( 0x50, drm_r128_fullscreen_t)
-#define DRM_IOCTL_R128_CLEAR2		DRM_IOW( 0x51, drm_r128_clear2_t)
-#define DRM_IOCTL_R128_GETPARAM		DRM_IOW( 0x52, drm_r128_getparam_t)
-#define DRM_IOCTL_R128_FLIP		DRM_IO(  0x53)
+#define DRM_R128_INIT       0x00
+#define DRM_R128_CCE_START  0x01
+#define DRM_R128_CCE_STOP   0x02
+#define DRM_R128_CCE_RESET  0x03
+#define DRM_R128_CCE_IDLE   0x04
+/* 0x05 not used */
+#define DRM_R128_RESET      0x06
+#define DRM_R128_SWAP       0x07
+#define DRM_R128_CLEAR      0x08
+#define DRM_R128_VERTEX     0x09
+#define DRM_R128_INDICES    0x0a
+#define DRM_R128_BLIT       0x0b
+#define DRM_R128_DEPTH      0x0c
+#define DRM_R128_STIPPLE    0x0d
+/* 0x0e not used */
+#define DRM_R128_INDIRECT   0x0f
+#define DRM_R128_FULLSCREEN 0x10
+#define DRM_R128_CLEAR2     0x11
+#define DRM_R128_GETPARAM   0x12
+#define DRM_R128_FLIP       0x13
+
+#define DRM_IOCTL_R128_INIT       DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t)
+#define DRM_IOCTL_R128_CCE_START  DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_START)
+#define DRM_IOCTL_R128_CCE_STOP   DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t)
+#define DRM_IOCTL_R128_CCE_RESET  DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_RESET)
+#define DRM_IOCTL_R128_CCE_IDLE   DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_IDLE)
+/* 0x05 not used */
+#define DRM_IOCTL_R128_RESET      DRM_IO(  DRM_COMMAND_BASE + DRM_R128_RESET)
+#define DRM_IOCTL_R128_SWAP       DRM_IO(  DRM_COMMAND_BASE + DRM_R128_SWAP)
+#define DRM_IOCTL_R128_CLEAR      DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t)
+#define DRM_IOCTL_R128_VERTEX     DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t)
+#define DRM_IOCTL_R128_INDICES    DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t)
+#define DRM_IOCTL_R128_BLIT       DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t)
+#define DRM_IOCTL_R128_DEPTH      DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t)
+#define DRM_IOCTL_R128_STIPPLE    DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t)
+/* 0x0e not used */
+#define DRM_IOCTL_R128_INDIRECT   DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t)
+#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t)
+#define DRM_IOCTL_R128_CLEAR2     DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t)
+#define DRM_IOCTL_R128_GETPARAM   DRM_IOW( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
+#define DRM_IOCTL_R128_FLIP       DRM_IO(  DRM_COMMAND_BASE + DRM_R128_FLIP)
 
 typedef struct drm_r128_init {
 	enum {
@@ -316,7 +339,7 @@
 
 typedef struct drm_r128_getparam {
 	int param;
-	int *value;
+	void *value;
 } drm_r128_getparam_t;
 
 #endif
diff -Nru a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
--- a/drivers/char/drm/r128_drv.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/r128_drv.c	Wed Apr 14 18:25:42 2004
@@ -47,6 +47,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "drm_lock.h"
 #include "drm_memory.h"
 #include "drm_proc.h"
diff -Nru a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
--- a/drivers/char/drm/r128_drv.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/r128_drv.h	Wed Apr 14 18:25:42 2004
@@ -34,8 +34,7 @@
 #ifndef __R128_DRV_H__
 #define __R128_DRV_H__
 
-#define GET_RING_HEAD(ring)		DRM_READ32(  (ring)->ring_rptr, 0 ) /* (ring)->head */
-#define SET_RING_HEAD(ring,val)		DRM_WRITE32( (ring)->ring_rptr, 0, (val) ) /* (ring)->head */
+#define GET_RING_HEAD(dev_priv)		R128_READ( R128_PM4_BUFFER_DL_RPTR )
 
 typedef struct drm_r128_freelist {
    	unsigned int age;
@@ -50,13 +49,11 @@
 	int size;
 	int size_l2qw;
 
-	volatile u32 *head;
 	u32 tail;
 	u32 tail_mask;
 	int space;
 
 	int high_mark;
-	drm_local_map_t *ring_rptr;
 } drm_r128_ring_buffer_t;
 
 typedef struct drm_r128_private {
@@ -100,7 +97,6 @@
 	u32 span_pitch_offset_c;
 
 	drm_local_map_t *sarea;
-	drm_local_map_t *fb;
 	drm_local_map_t *mmio;
 	drm_local_map_t *cce_ring;
 	drm_local_map_t *ring_rptr;
@@ -132,14 +128,6 @@
 
 extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
 
-static __inline__ void
-r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring )
-{
-	ring->space = (GET_RING_HEAD( ring ) - ring->tail) * sizeof(u32);
-	if ( ring->space <= 0 )
-		ring->space += ring->size;
-}
-
 extern int r128_do_cce_idle( drm_r128_private_t *dev_priv );
 extern int r128_do_cleanup_cce( drm_device_t *dev );
 extern int r128_do_cleanup_pageflip( drm_device_t *dev );
@@ -279,6 +267,7 @@
 #	define R128_PM4_64PIO_64VCBM_64INDBM	(7  << 28)
 #	define R128_PM4_64BM_64VCBM_64INDBM	(8  << 28)
 #	define R128_PM4_64PIO_64VCPIO_64INDPIO	(15 << 28)
+#	define R128_PM4_BUFFER_CNTL_NOUPDATE	(1  << 27)
 
 #define R128_PM4_BUFFER_WM_CNTL		0x0708
 #	define R128_WMA_SHIFT			0
@@ -403,6 +392,15 @@
 					 (pkt) | ((n) << 16))
 
 
+static __inline__ void
+r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
+{
+	drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+	ring->space = (GET_RING_HEAD( dev_priv ) - ring->tail) * sizeof(u32);
+	if ( ring->space <= 0 )
+		ring->space += ring->size;
+}
+
 /* ================================================================
  * Misc helper macros
  */
@@ -412,7 +410,7 @@
 	drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i;		\
 	if ( ring->space < ring->high_mark ) {				\
 		for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {	\
-			r128_update_ring_snapshot( ring );		\
+			r128_update_ring_snapshot( dev_priv );		\
 			if ( ring->space >= ring->high_mark )		\
 				goto __ring_space_done;			\
 			DRM_UDELAY(1);				\
@@ -445,17 +443,10 @@
  * Ring control
  */
 
-#if defined(__powerpc__)
-#define r128_flush_write_combine()	(void) GET_RING_HEAD( &dev_priv->ring )
-#else
-#define r128_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
-#endif
-
-
 #define R128_VERBOSE	0
 
 #define RING_LOCALS							\
-	int write; unsigned int tail_mask; volatile u32 *ring;
+	int write, _nr; unsigned int tail_mask; volatile u32 *ring;
 
 #define BEGIN_RING( n ) do {						\
 	if ( R128_VERBOSE ) {						\
@@ -463,9 +454,10 @@
 			   (n), __FUNCTION__ );				\
 	}								\
 	if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {		\
+		COMMIT_RING();						\
 		r128_wait_ring( dev_priv, (n) * sizeof(u32) );		\
 	}								\
-	dev_priv->ring.space -= (n) * sizeof(u32);			\
+	_nr = n; dev_priv->ring.space -= (n) * sizeof(u32);		\
 	ring = dev_priv->ring.start;					\
 	write = dev_priv->ring.tail;					\
 	tail_mask = dev_priv->ring.tail_mask;				\
@@ -488,9 +480,23 @@
 			dev_priv->ring.start,				\
 			write * sizeof(u32) );				\
 	}								\
-	r128_flush_write_combine();					\
-	dev_priv->ring.tail = write;					\
-	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );			\
+	if (((dev_priv->ring.tail + _nr) & tail_mask) != write) {	\
+		DRM_ERROR( 						\
+			"ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",	\
+			((dev_priv->ring.tail + _nr) & tail_mask),	\
+			write, __LINE__);				\
+	} else								\
+		dev_priv->ring.tail = write;				\
+} while (0)
+
+#define COMMIT_RING() do {						\
+	if ( R128_VERBOSE ) {						\
+		DRM_INFO( "COMMIT_RING() tail=0x%06x\n",		\
+			dev_priv->ring.tail );				\
+	}								\
+	DRM_MEMORYBARRIER();						\
+	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail );	\
+	R128_READ( R128_PM4_BUFFER_DL_WPTR );				\
 } while (0)
 
 #define OUT_RING( x ) do {						\
diff -Nru a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
--- a/drivers/char/drm/r128_irq.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/r128_irq.c	Wed Apr 14 18:25:42 2004
@@ -36,7 +36,7 @@
 #include "r128_drm.h"
 #include "r128_drv.h"
 
-irqreturn_t r128_dma_service( DRM_IRQ_ARGS )
+irqreturn_t r128_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_r128_private_t *dev_priv = 
diff -Nru a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
--- a/drivers/char/drm/r128_state.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/r128_state.c	Wed Apr 14 18:25:42 2004
@@ -45,7 +45,7 @@
 	RING_LOCALS;
 	DRM_DEBUG( "    %s\n", __FUNCTION__ );
 
-	BEGIN_RING( 17 );
+	BEGIN_RING( (count < 3? count: 3) * 5 + 2 );
 
 	if ( count >= 1 ) {
 		OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
@@ -1011,7 +1011,7 @@
 	DRM_DEBUG( "\n" );
 
 	count = depth->n;
-	if (count > 4096  || count <= 0)
+	if (count > 4096 || count <= 0)
 		return -EMSGSIZE;
 
 	xbuf_size = count * sizeof(*x);
@@ -1280,6 +1280,7 @@
 		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
 
 	r128_cce_dispatch_clear( dev, &clear );
+	COMMIT_RING();
 
 	/* Make sure we restore the 3D state next time.
 	 */
@@ -1315,8 +1316,10 @@
 	R128_WRITE( R128_CRTC_OFFSET,      dev_priv->crtc_offset );
 	R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
 
-	if (dev_priv->current_page != 0)
+	if (dev_priv->current_page != 0) {
 		r128_cce_dispatch_flip( dev );
+		COMMIT_RING();
+	}
 
 	dev_priv->page_flipping = 0;
 	return 0;
@@ -1341,6 +1344,7 @@
 
 	r128_cce_dispatch_flip( dev );
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1362,6 +1366,7 @@
 	dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
 					R128_UPLOAD_MASKS);
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1421,6 +1426,7 @@
 
 	r128_cce_dispatch_vertex( dev, buf );
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1492,6 +1498,7 @@
 
 	r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1501,6 +1508,7 @@
 	drm_device_dma_t *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_blit_t blit;
+	int ret;
 
 	LOCK_TEST_WITH_RETURN( dev, filp );
 
@@ -1518,7 +1526,10 @@
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
-	return r128_cce_dispatch_blit( filp, dev, &blit );
+	ret = r128_cce_dispatch_blit( filp, dev, &blit );
+
+	COMMIT_RING();
+	return ret;
 }
 
 int r128_cce_depth( DRM_IOCTL_ARGS )
@@ -1526,6 +1537,7 @@
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_depth_t depth;
+	int ret;
 
 	LOCK_TEST_WITH_RETURN( dev, filp );
 
@@ -1534,18 +1546,20 @@
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
+	ret = DRM_ERR(EINVAL);
 	switch ( depth.func ) {
 	case R128_WRITE_SPAN:
-		return r128_cce_dispatch_write_span( dev, &depth );
+		ret = r128_cce_dispatch_write_span( dev, &depth );
 	case R128_WRITE_PIXELS:
-		return r128_cce_dispatch_write_pixels( dev, &depth );
+		ret = r128_cce_dispatch_write_pixels( dev, &depth );
 	case R128_READ_SPAN:
-		return r128_cce_dispatch_read_span( dev, &depth );
+		ret = r128_cce_dispatch_read_span( dev, &depth );
 	case R128_READ_PIXELS:
-		return r128_cce_dispatch_read_pixels( dev, &depth );
+		ret = r128_cce_dispatch_read_pixels( dev, &depth );
 	}
 
-	return DRM_ERR(EINVAL);
+	COMMIT_RING();
+	return ret;
 }
 
 int r128_cce_stipple( DRM_IOCTL_ARGS )
@@ -1568,6 +1582,7 @@
 
 	r128_cce_dispatch_stipple( dev, mask );
 
+	COMMIT_RING();
 	return 0;
 }
 
@@ -1643,6 +1658,7 @@
 	 */
 	r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
 
+	COMMIT_RING();
 	return 0;
 }
 
diff -Nru a/drivers/char/drm/radeon.h b/drivers/char/drm/radeon.h
--- a/drivers/char/drm/radeon.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/radeon.h	Wed Apr 14 18:25:42 2004
@@ -51,7 +51,7 @@
 #define DRIVER_DATE		"20020828"
 
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		9
+#define DRIVER_MINOR		10
 #define DRIVER_PATCHLEVEL	0
 
 /* Interface history:
@@ -81,6 +81,9 @@
  *       Add 'GET' queries for starting additional clients on different VT's.
  * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
  *       Add texture rectangle support for r100.
+ * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
+ *       clients use to tell the DRM where they think the framebuffer is 
+ *       located in the card's address space
  */
 #define DRIVER_IOCTLS							     \
  [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
@@ -106,10 +109,82 @@
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)]      = { radeon_mem_alloc,   1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)]       = { radeon_mem_free,    1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)]  = { radeon_mem_init_heap, 1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)]   = { radeon_irq_emit, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)]   = { radeon_irq_emit,    1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait,    1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)]   = { radeon_cp_setparam, 1, 0 }, \
+
+#define DRIVER_PCI_IDS							\
+	{0x1002, 0x4136, 0},						\
+	{0x1002, 0x4137, 0},						\
+	{0x1002, 0x4237, 0},						\
+	{0x1002, 0x4242, 0},						\
+	{0x1002, 0x4242, 0},						\
+	{0x1002, 0x4336, 0},						\
+	{0x1002, 0x4337, 0},						\
+	{0x1002, 0x4437, 0},						\
+	{0x1002, 0x4964, 0},						\
+	{0x1002, 0x4965, 0},						\
+	{0x1002, 0x4966, 0},						\
+	{0x1002, 0x4967, 0},						\
+	{0x1002, 0x4C57, 0},						\
+	{0x1002, 0x4C58, 0},						\
+	{0x1002, 0x4C59, 0},						\
+	{0x1002, 0x4C5A, 0},						\
+	{0x1002, 0x4C64, 0},						\
+	{0x1002, 0x4C65, 0},						\
+	{0x1002, 0x4C66, 0},						\
+	{0x1002, 0x4C67, 0},						\
+	{0x1002, 0x5144, 0},						\
+	{0x1002, 0x5145, 0},						\
+	{0x1002, 0x5146, 0},						\
+	{0x1002, 0x5147, 0},						\
+	{0x1002, 0x5148, 0},						\
+	{0x1002, 0x5149, 0},						\
+	{0x1002, 0x514A, 0},						\
+	{0x1002, 0x514B, 0},						\
+	{0x1002, 0x514C, 0},						\
+	{0x1002, 0x514D, 0},						\
+	{0x1002, 0x514E, 0},						\
+	{0x1002, 0x514F, 0},						\
+	{0x1002, 0x5157, 0},						\
+	{0x1002, 0x5158, 0},						\
+	{0x1002, 0x5159, 0},						\
+	{0x1002, 0x515A, 0},						\
+	{0x1002, 0x5168, 0},						\
+	{0x1002, 0x5169, 0},						\
+	{0x1002, 0x516A, 0},						\
+	{0x1002, 0x516B, 0},						\
+	{0x1002, 0x516C, 0},						\
+	{0x1002, 0x5834, 0},						\
+	{0x1002, 0x5835, 0},						\
+	{0x1002, 0x5836, 0},						\
+	{0x1002, 0x5837, 0},						\
+	{0x1002, 0x5960, 0},						\
+	{0x1002, 0x5961, 0},						\
+	{0x1002, 0x5962, 0},						\
+	{0x1002, 0x5963, 0},						\
+	{0x1002, 0x5964, 0},						\
+	{0x1002, 0x5968, 0},						\
+	{0x1002, 0x5969, 0},						\
+	{0x1002, 0x596A, 0},						\
+	{0x1002, 0x596B, 0},						\
+	{0x1002, 0x5c61, 0},						\
+	{0x1002, 0x5c62, 0},						\
+	{0x1002, 0x5c63, 0},						\
+	{0x1002, 0x5c64, 0},						\
+	{0, 0, 0}
 
+#define DRIVER_FILE_FIELDS						\
+	int64_t radeon_fb_delta;					\
 
+#define DRIVER_OPEN_HELPER( filp_priv, dev )				\
+do {									\
+	drm_radeon_private_t *dev_priv = dev->dev_private;		\
+	if ( dev_priv )							\
+		filp_priv->radeon_fb_delta = dev_priv->fb_location;	\
+	else								\
+		filp_priv->radeon_fb_delta = 0;				\
+} while( 0 )
 
 /* When a client dies:
  *    - Check for and clean up flipped page state
@@ -142,7 +217,7 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
-#define __HAVE_DMA_IRQ		1
+#define __HAVE_IRQ		1
 #define __HAVE_VBL_IRQ		1
 #define __HAVE_SHARED_IRQ       1
 
diff -Nru a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
--- a/drivers/char/drm/radeon_cp.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/radeon_cp.c	Wed Apr 14 18:25:42 2004
@@ -855,7 +855,8 @@
 
 	/* Initialize the memory controller */
 	RADEON_WRITE( RADEON_MC_FB_LOCATION,
-		      (dev_priv->gart_vm_start - 1) & 0xffff0000 );
+		      ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
+		    | ( dev_priv->fb_location >> 16 ) );
 
 #if __REALLY_HAVE_AGP
 	if ( !dev_priv->is_pci ) {
@@ -1071,13 +1072,6 @@
 	dev_priv->depth_offset	= init->depth_offset;
 	dev_priv->depth_pitch	= init->depth_pitch;
 
-	dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
-					(dev_priv->front_offset >> 10));
-	dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
-				       (dev_priv->back_offset >> 10));
-	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
-					(dev_priv->depth_offset >> 10));
-
 	/* Hardware state for depth clears.  Remove this if/when we no
 	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
 	 * all values to prevent unwanted 3D state from slipping through
@@ -1124,13 +1118,6 @@
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
-	if(!dev_priv->fb) {
-		DRM_ERROR("could not find framebuffer!\n");
-		dev->dev_private = (void *)dev_priv;
-		radeon_do_cleanup_cp(dev);
-		return DRM_ERR(EINVAL);
-	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
@@ -1204,9 +1191,26 @@
 			   dev_priv->buffers->handle );
 	}
 
+	dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
+				& 0xffff ) << 16;
+
+	dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
+					( ( dev_priv->front_offset
+					  + dev_priv->fb_location ) >> 10 ) );
+
+	dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
+				       ( ( dev_priv->back_offset
+					 + dev_priv->fb_location ) >> 10 ) );
+
+	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
+					( ( dev_priv->depth_offset
+					  + dev_priv->fb_location ) >> 10 ) );
+
 
 	dev_priv->gart_size = init->gart_size;
-	dev_priv->gart_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
+	dev_priv->gart_vm_start = dev_priv->fb_location
+				+ RADEON_READ( RADEON_CONFIG_APER_SIZE );
+
 #if __REALLY_HAVE_AGP
 	if ( !dev_priv->is_pci )
 		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
@@ -1271,12 +1275,12 @@
 {
 	DRM_DEBUG( "\n" );
 
-#if _HAVE_DMA_IRQ
+#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq ) DRM(irq_uninstall)(dev);
+	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
 #endif
 
 	if ( dev->dev_private ) {
diff -Nru a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
--- a/drivers/char/drm/radeon_drm.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/radeon_drm.h	Wed Apr 14 18:25:42 2004
@@ -226,6 +226,13 @@
 #define RADEON_MAX_TEXTURE_LEVELS	12
 #define RADEON_MAX_TEXTURE_UNITS	3
 
+/* Blits have strict offset rules.  All blit offset must be aligned on
+ * a 1K-byte boundary.
+ */
+#define RADEON_OFFSET_SHIFT             10
+#define RADEON_OFFSET_ALIGN             (1 << RADEON_OFFSET_SHIFT)
+#define RADEON_OFFSET_MASK              (RADEON_OFFSET_ALIGN - 1)
+
 #endif /* __RADEON_SAREA_DEFINES__ */
 
 typedef struct {
@@ -365,31 +372,58 @@
 /* Radeon specific ioctls
  * The device specific ioctl range is 0x40 to 0x79.
  */
-#define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( 0x40, drm_radeon_init_t)
-#define DRM_IOCTL_RADEON_CP_START   DRM_IO(  0x41)
-#define DRM_IOCTL_RADEON_CP_STOP    DRM_IOW( 0x42, drm_radeon_cp_stop_t)
-#define DRM_IOCTL_RADEON_CP_RESET   DRM_IO(  0x43)
-#define DRM_IOCTL_RADEON_CP_IDLE    DRM_IO(  0x44)
-#define DRM_IOCTL_RADEON_RESET      DRM_IO(  0x45)
-#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t)
-#define DRM_IOCTL_RADEON_SWAP       DRM_IO(  0x47)
-#define DRM_IOCTL_RADEON_CLEAR      DRM_IOW( 0x48, drm_radeon_clear_t)
-#define DRM_IOCTL_RADEON_VERTEX     DRM_IOW( 0x49, drm_radeon_vertex_t)
-#define DRM_IOCTL_RADEON_INDICES    DRM_IOW( 0x4a, drm_radeon_indices_t)
-#define DRM_IOCTL_RADEON_STIPPLE    DRM_IOW( 0x4c, drm_radeon_stipple_t)
-#define DRM_IOCTL_RADEON_INDIRECT   DRM_IOWR(0x4d, drm_radeon_indirect_t)
-#define DRM_IOCTL_RADEON_TEXTURE    DRM_IOWR(0x4e, drm_radeon_texture_t)
-#define DRM_IOCTL_RADEON_VERTEX2    DRM_IOW( 0x4f, drm_radeon_vertex2_t)
-#define DRM_IOCTL_RADEON_CMDBUF     DRM_IOW( 0x50, drm_radeon_cmd_buffer_t)
-#define DRM_IOCTL_RADEON_GETPARAM   DRM_IOWR(0x51, drm_radeon_getparam_t)
-#define DRM_IOCTL_RADEON_FLIP	    DRM_IO(  0x52)
-#define DRM_IOCTL_RADEON_ALLOC      DRM_IOWR( 0x53, drm_radeon_mem_alloc_t)
-#define DRM_IOCTL_RADEON_FREE       DRM_IOW( 0x54, drm_radeon_mem_free_t)
-#define DRM_IOCTL_RADEON_INIT_HEAP  DRM_IOW( 0x55, drm_radeon_mem_init_heap_t)
-#define DRM_IOCTL_RADEON_IRQ_EMIT   DRM_IOWR( 0x56, drm_radeon_irq_emit_t)
-#define DRM_IOCTL_RADEON_IRQ_WAIT   DRM_IOW( 0x57, drm_radeon_irq_wait_t)
-/* added by Charl P. Botha - see radeon_cp.c for details */
-#define DRM_IOCTL_RADEON_CP_RESUME  DRM_IO(0x58)
+#define DRM_RADEON_CP_INIT    0x00 
+#define DRM_RADEON_CP_START   0x01 
+#define DRM_RADEON_CP_STOP    0x02
+#define DRM_RADEON_CP_RESET   0x03
+#define DRM_RADEON_CP_IDLE    0x04
+#define DRM_RADEON_RESET      0x05 
+#define DRM_RADEON_FULLSCREEN 0x06
+#define DRM_RADEON_SWAP       0x07 
+#define DRM_RADEON_CLEAR      0x08 
+#define DRM_RADEON_VERTEX     0x09
+#define DRM_RADEON_INDICES    0x0A
+#define DRM_RADEON_NOT_USED
+#define DRM_RADEON_STIPPLE    0x0C
+#define DRM_RADEON_INDIRECT   0x0D
+#define DRM_RADEON_TEXTURE    0x0E
+#define DRM_RADEON_VERTEX2    0x0F
+#define DRM_RADEON_CMDBUF     0x10
+#define DRM_RADEON_GETPARAM   0x11
+#define DRM_RADEON_FLIP       0x12
+#define DRM_RADEON_ALLOC      0x13
+#define DRM_RADEON_FREE       0x14
+#define DRM_RADEON_INIT_HEAP  0x15
+#define DRM_RADEON_IRQ_EMIT   0x16
+#define DRM_RADEON_IRQ_WAIT   0x17
+#define DRM_RADEON_CP_RESUME  0x18
+#define DRM_RADEON_SETPARAM   0x19
+
+#define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
+#define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
+#define DRM_IOCTL_RADEON_CP_STOP    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t)
+#define DRM_IOCTL_RADEON_CP_RESET   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_RESET)
+#define DRM_IOCTL_RADEON_CP_IDLE    DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE)
+#define DRM_IOCTL_RADEON_RESET      DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_RESET)
+#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t)
+#define DRM_IOCTL_RADEON_SWAP       DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_SWAP)
+#define DRM_IOCTL_RADEON_CLEAR      DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t)
+#define DRM_IOCTL_RADEON_VERTEX     DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t)
+#define DRM_IOCTL_RADEON_INDICES    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t)
+#define DRM_IOCTL_RADEON_STIPPLE    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t)
+#define DRM_IOCTL_RADEON_INDIRECT   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t)
+#define DRM_IOCTL_RADEON_TEXTURE    DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t)
+#define DRM_IOCTL_RADEON_VERTEX2    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t)
+#define DRM_IOCTL_RADEON_CMDBUF     DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t)
+#define DRM_IOCTL_RADEON_GETPARAM   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t)
+#define DRM_IOCTL_RADEON_FLIP       DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_FLIP)
+#define DRM_IOCTL_RADEON_ALLOC      DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t)
+#define DRM_IOCTL_RADEON_FREE       DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t)
+#define DRM_IOCTL_RADEON_INIT_HEAP  DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t)
+#define DRM_IOCTL_RADEON_IRQ_EMIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t)
+#define DRM_IOCTL_RADEON_IRQ_WAIT   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t)
+#define DRM_IOCTL_RADEON_CP_RESUME  DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME)
+#define DRM_IOCTL_RADEON_SETPARAM   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
 
 typedef struct drm_radeon_init {
 	enum {
@@ -502,7 +536,7 @@
 } drm_radeon_tex_image_t;
 
 typedef struct drm_radeon_texture {
-	int offset;
+	unsigned int offset;
 	int pitch;
 	int format;
 	int width;			/* Texture image coordinates */
@@ -537,10 +571,11 @@
 #define RADEON_PARAM_STATUS_HANDLE         8
 #define RADEON_PARAM_SAREA_HANDLE          9
 #define RADEON_PARAM_GART_TEX_HANDLE       10
+#define RADEON_PARAM_SCRATCH_OFFSET        11
 
 typedef struct drm_radeon_getparam {
 	int param;
-	int *value;
+	void *value;
 } drm_radeon_getparam_t;
 
 /* 1.6: Set up a memory manager for regions of shared memory:
@@ -576,6 +611,18 @@
 typedef struct drm_radeon_irq_wait {
 	int irq_seq;
 } drm_radeon_irq_wait_t;
+
+
+/* 1.10: Clients tell the DRM where they think the framebuffer is located in
+ * the card's address space, via a new generic ioctl to set parameters
+ */
+
+typedef struct drm_radeon_setparam {
+	unsigned int param;
+	int64_t      value;
+} drm_radeon_setparam_t;
+
+#define RADEON_SETPARAM_FB_LOCATION    1 /* determined framebuffer location */
 
 
 #endif
diff -Nru a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
--- a/drivers/char/drm/radeon_drv.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/radeon_drv.c	Wed Apr 14 18:25:42 2004
@@ -48,6 +48,7 @@
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
+#include "drm_irq.h"
 #include "drm_lock.h"
 #include "drm_memory.h"
 #include "drm_proc.h"
diff -Nru a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
--- a/drivers/char/drm/radeon_drv.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/radeon_drv.h	Wed Apr 14 18:25:42 2004
@@ -73,6 +73,8 @@
 	drm_radeon_ring_buffer_t ring;
 	drm_radeon_sarea_t *sarea_priv;
 
+	u32 fb_location;
+
 	int gart_size;
 	u32 gart_vm_start;
 	unsigned long gart_buffers_offset;
@@ -133,7 +135,6 @@
 	unsigned long gart_textures_offset;
 
 	drm_local_map_t *sarea;
-	drm_local_map_t *fb;
 	drm_local_map_t *mmio;
 	drm_local_map_t *cp_ring;
 	drm_local_map_t *ring_rptr;
@@ -184,6 +185,7 @@
 extern int radeon_cp_vertex2( DRM_IOCTL_ARGS );
 extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
 extern int radeon_cp_getparam( DRM_IOCTL_ARGS );
+extern int radeon_cp_setparam( DRM_IOCTL_ARGS );
 extern int radeon_cp_flip( DRM_IOCTL_ARGS );
 
 extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
@@ -239,6 +241,7 @@
 #define RADEON_CRTC2_OFFSET		0x0324
 #define RADEON_CRTC2_OFFSET_CNTL	0x0328
 
+#define RADEON_RB3D_COLOROFFSET		0x1c40
 #define RADEON_RB3D_COLORPITCH		0x1c48
 
 #define RADEON_DP_GUI_MASTER_CNTL	0x146c
@@ -332,6 +335,7 @@
 #define RADEON_PP_MISC			0x1c14
 #define RADEON_PP_ROT_MATRIX_0		0x1d58
 #define RADEON_PP_TXFILTER_0		0x1c54
+#define RADEON_PP_TXOFFSET_0		0x1c5c
 #define RADEON_PP_TXFILTER_1		0x1c6c
 #define RADEON_PP_TXFILTER_2		0x1c84
 
diff -Nru a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
--- a/drivers/char/drm/radeon_irq.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/radeon_irq.c	Wed Apr 14 18:25:42 2004
@@ -54,7 +54,7 @@
  * tied to dma at all, this is just a hangover from dri prehistory.
  */
 
-irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS )
+irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_radeon_private_t *dev_priv = 
diff -Nru a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
--- a/drivers/char/drm/radeon_state.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/radeon_state.c	Wed Apr 14 18:25:42 2004
@@ -36,6 +36,240 @@
 
 
 /* ================================================================
+ * Helper functions for client state checking and fixup
+ */
+
+static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv,
+						     drm_file_t *filp_priv,
+						     u32 *offset ) {
+	u32 off = *offset;
+
+	if ( off >= dev_priv->fb_location &&
+	     off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+		return 0;
+
+	off += filp_priv->radeon_fb_delta;
+
+	DRM_DEBUG( "offset fixed up to 0x%x\n", off );
+
+	if ( off < dev_priv->fb_location ||
+	     off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+		return DRM_ERR( EINVAL );
+
+	*offset = off;
+
+	return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_offset_user( drm_radeon_private_t *dev_priv,
+							  drm_file_t *filp_priv,
+							  u32 *offset ) {
+	u32 off;
+
+	DRM_GET_USER_UNCHECKED( off, offset );
+
+	if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &off ) )
+		return DRM_ERR( EINVAL );
+
+	DRM_PUT_USER_UNCHECKED( offset, off );
+
+	return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
+						      drm_file_t *filp_priv,
+						      int id,
+						      u32 *data ) {
+	switch ( id ) {
+
+	case RADEON_EMIT_PP_MISC:
+		if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+							 &data[( RADEON_RB3D_DEPTHOFFSET
+								 - RADEON_PP_MISC ) / 4] ) ) {
+			DRM_ERROR( "Invalid depth buffer offset\n" );
+			return DRM_ERR( EINVAL );
+		}
+		break;
+
+	case RADEON_EMIT_PP_CNTL:
+		if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+							 &data[( RADEON_RB3D_COLOROFFSET
+								 - RADEON_PP_CNTL ) / 4] ) ) {
+			DRM_ERROR( "Invalid colour buffer offset\n" );
+			return DRM_ERR( EINVAL );
+		}
+		break;
+
+	case R200_EMIT_PP_TXOFFSET_0:
+	case R200_EMIT_PP_TXOFFSET_1:
+	case R200_EMIT_PP_TXOFFSET_2:
+	case R200_EMIT_PP_TXOFFSET_3:
+	case R200_EMIT_PP_TXOFFSET_4:
+	case R200_EMIT_PP_TXOFFSET_5:
+		if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+							 &data[0] ) ) {
+			DRM_ERROR( "Invalid R200 texture offset\n" );
+			return DRM_ERR( EINVAL );
+		}
+		break;
+
+	case RADEON_EMIT_PP_TXFILTER_0:
+	case RADEON_EMIT_PP_TXFILTER_1:
+	case RADEON_EMIT_PP_TXFILTER_2:
+		if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+							 &data[( RADEON_PP_TXOFFSET_0
+								 - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
+			DRM_ERROR( "Invalid R100 texture offset\n" );
+			return DRM_ERR( EINVAL );
+		}
+		break;
+
+	case R200_EMIT_PP_CUBIC_OFFSETS_0:
+	case R200_EMIT_PP_CUBIC_OFFSETS_1:
+	case R200_EMIT_PP_CUBIC_OFFSETS_2:
+	case R200_EMIT_PP_CUBIC_OFFSETS_3:
+	case R200_EMIT_PP_CUBIC_OFFSETS_4:
+	case R200_EMIT_PP_CUBIC_OFFSETS_5: {
+		int i;
+		for ( i = 0; i < 5; i++ ) {
+			if ( radeon_check_and_fixup_offset_user( dev_priv,
+								 filp_priv,
+								 &data[i] ) ) {
+				DRM_ERROR( "Invalid R200 cubic texture offset\n" );
+				return DRM_ERR( EINVAL );
+			}
+		}
+		break;
+	}
+
+	case RADEON_EMIT_RB3D_COLORPITCH:
+	case RADEON_EMIT_RE_LINE_PATTERN:
+	case RADEON_EMIT_SE_LINE_WIDTH:
+	case RADEON_EMIT_PP_LUM_MATRIX:
+	case RADEON_EMIT_PP_ROT_MATRIX_0:
+	case RADEON_EMIT_RB3D_STENCILREFMASK:
+	case RADEON_EMIT_SE_VPORT_XSCALE:
+	case RADEON_EMIT_SE_CNTL:
+	case RADEON_EMIT_SE_CNTL_STATUS:
+	case RADEON_EMIT_RE_MISC:
+	case RADEON_EMIT_PP_BORDER_COLOR_0:
+	case RADEON_EMIT_PP_BORDER_COLOR_1:
+	case RADEON_EMIT_PP_BORDER_COLOR_2:
+	case RADEON_EMIT_SE_ZBIAS_FACTOR:
+	case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
+	case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
+	case R200_EMIT_PP_TXCBLEND_0:
+	case R200_EMIT_PP_TXCBLEND_1:
+	case R200_EMIT_PP_TXCBLEND_2:
+	case R200_EMIT_PP_TXCBLEND_3:
+	case R200_EMIT_PP_TXCBLEND_4:
+	case R200_EMIT_PP_TXCBLEND_5:
+	case R200_EMIT_PP_TXCBLEND_6:
+	case R200_EMIT_PP_TXCBLEND_7:
+	case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
+	case R200_EMIT_TFACTOR_0:
+	case R200_EMIT_VTX_FMT_0:
+	case R200_EMIT_VAP_CTL:
+	case R200_EMIT_MATRIX_SELECT_0:
+	case R200_EMIT_TEX_PROC_CTL_2:
+	case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
+	case R200_EMIT_PP_TXFILTER_0:
+	case R200_EMIT_PP_TXFILTER_1:
+	case R200_EMIT_PP_TXFILTER_2:
+	case R200_EMIT_PP_TXFILTER_3:
+	case R200_EMIT_PP_TXFILTER_4:
+	case R200_EMIT_PP_TXFILTER_5:
+	case R200_EMIT_VTE_CNTL:
+	case R200_EMIT_OUTPUT_VTX_COMP_SEL:
+	case R200_EMIT_PP_TAM_DEBUG3:
+	case R200_EMIT_PP_CNTL_X:
+	case R200_EMIT_RB3D_DEPTHXY_OFFSET:
+	case R200_EMIT_RE_AUX_SCISSOR_CNTL:
+	case R200_EMIT_RE_SCISSOR_TL_0:
+	case R200_EMIT_RE_SCISSOR_TL_1:
+	case R200_EMIT_RE_SCISSOR_TL_2:
+	case R200_EMIT_SE_VAP_CNTL_STATUS:
+	case R200_EMIT_SE_VTX_STATE_CNTL:
+	case R200_EMIT_RE_POINTSIZE:
+	case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
+	case R200_EMIT_PP_CUBIC_FACES_0:
+	case R200_EMIT_PP_CUBIC_FACES_1:
+	case R200_EMIT_PP_CUBIC_FACES_2:
+	case R200_EMIT_PP_CUBIC_FACES_3:
+	case R200_EMIT_PP_CUBIC_FACES_4:
+	case R200_EMIT_PP_CUBIC_FACES_5:
+	case RADEON_EMIT_PP_TEX_SIZE_0:
+	case RADEON_EMIT_PP_TEX_SIZE_1:
+	case RADEON_EMIT_PP_TEX_SIZE_2:
+		/* These packets don't contain memory offsets */
+		break;
+
+	default:
+		DRM_ERROR( "Unknown state packet ID %d\n", id );
+		return DRM_ERR( EINVAL );
+	}
+
+	return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv,
+						      drm_file_t *filp_priv,
+						      drm_radeon_cmd_buffer_t *cmdbuf,
+						      unsigned int *cmdsz ) {
+	u32 tmp[4], *cmd = ( u32* )cmdbuf->buf;
+
+	if ( DRM_COPY_FROM_USER_UNCHECKED( tmp, cmd, sizeof( tmp ) ) ) {
+		DRM_ERROR( "Failed to copy data from user space\n" );
+		return DRM_ERR( EFAULT );
+	}
+
+	*cmdsz = 2 + ( ( tmp[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
+
+	if ( ( tmp[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
+		DRM_ERROR( "Not a type 3 packet\n" );
+		return DRM_ERR( EINVAL );
+	}
+
+	if ( 4 * *cmdsz > cmdbuf->bufsz ) {
+		DRM_ERROR( "Packet size larger than size of data provided\n" );
+		return DRM_ERR( EINVAL );
+	}
+
+	/* Check client state and fix it up if necessary */
+	if ( tmp[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
+		u32 offset;
+
+		if ( tmp[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+			offset = tmp[2] << 10;
+			if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+				DRM_ERROR( "Invalid first packet offset\n" );
+				return DRM_ERR( EINVAL );
+			}
+			tmp[2] = ( tmp[2] & 0xffc00000 ) | offset >> 10;
+		}
+
+		if ( ( tmp[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
+		     ( tmp[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+			offset = tmp[3] << 10;
+			if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+				DRM_ERROR( "Invalid second packet offset\n" );
+				return DRM_ERR( EINVAL );
+			}
+			tmp[3] = ( tmp[3] & 0xffc00000 ) | offset >> 10;
+		}
+
+		if ( DRM_COPY_TO_USER_UNCHECKED( cmd, tmp, sizeof( tmp ) ) ) {
+			DRM_ERROR( "Failed to copy data to user space\n" );
+			return DRM_ERR( EFAULT );
+		}
+	}
+
+	return 0;
+}
+
+
+/* ================================================================
  * CP hardware state programming functions
  */
 
@@ -57,15 +291,28 @@
 
 /* Emit 1.1 state
  */
-static void radeon_emit_state( drm_radeon_private_t *dev_priv,
-			       drm_radeon_context_regs_t *ctx,
-			       drm_radeon_texture_regs_t *tex,
-			       unsigned int dirty )
+static int radeon_emit_state( drm_radeon_private_t *dev_priv,
+			      drm_file_t *filp_priv,
+			      drm_radeon_context_regs_t *ctx,
+			      drm_radeon_texture_regs_t *tex,
+			      unsigned int dirty )
 {
 	RING_LOCALS;
 	DRM_DEBUG( "dirty=0x%08x\n", dirty );
 
 	if ( dirty & RADEON_UPLOAD_CONTEXT ) {
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &ctx->rb3d_depthoffset ) ) {
+			DRM_ERROR( "Invalid depth buffer offset\n" );
+			return DRM_ERR( EINVAL );
+		}
+
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &ctx->rb3d_coloroffset ) ) {
+			DRM_ERROR( "Invalid depth buffer offset\n" );
+			return DRM_ERR( EINVAL );
+		}
+
 		BEGIN_RING( 14 );
 		OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
 		OUT_RING( ctx->pp_misc );
@@ -149,6 +396,12 @@
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX0 ) {
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &tex[0].pp_txoffset ) ) {
+			DRM_ERROR( "Invalid texture offset for unit 0\n" );
+			return DRM_ERR( EINVAL );
+		}
+
 		BEGIN_RING( 9 );
 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
 		OUT_RING( tex[0].pp_txfilter );
@@ -163,6 +416,12 @@
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX1 ) {
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &tex[1].pp_txoffset ) ) {
+			DRM_ERROR( "Invalid texture offset for unit 1\n" );
+			return DRM_ERR( EINVAL );
+		}
+
 		BEGIN_RING( 9 );
 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
 		OUT_RING( tex[1].pp_txfilter );
@@ -177,6 +436,12 @@
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX2 ) {
+		if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+						    &tex[2].pp_txoffset ) ) {
+			DRM_ERROR( "Invalid texture offset for unit 2\n" );
+			return DRM_ERR( EINVAL );
+		}
+
 		BEGIN_RING( 9 );
 		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
 		OUT_RING( tex[2].pp_txfilter );
@@ -189,12 +454,15 @@
 		OUT_RING( tex[2].pp_border_color );
 		ADVANCE_RING();
 	}
+
+	return 0;
 }
 
 /* Emit 1.2 state
  */
-static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
-				drm_radeon_state_t *state )
+static int radeon_emit_state2( drm_radeon_private_t *dev_priv,
+			       drm_file_t *filp_priv,
+			       drm_radeon_state_t *state )
 {
 	RING_LOCALS;
 
@@ -206,7 +474,7 @@
 		ADVANCE_RING();
 	}
 
-	radeon_emit_state( dev_priv, &state->context, 
+	return radeon_emit_state( dev_priv, filp_priv, &state->context,
 			   state->tex, state->dirty );
 }
 
@@ -1065,6 +1333,7 @@
 				       drm_radeon_tex_image_t *image )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_buf_t *buf;
 	u32 format;
 	u32 *buffer;
@@ -1074,6 +1343,13 @@
 	int i;
 	RING_LOCALS;
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
+	if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) {
+		DRM_ERROR( "Invalid destination offset\n" );
+		return DRM_ERR( EINVAL );
+	}
+
 	dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
 
 	/* Flush the pixel cache.  This ensures no pixel data gets mixed
@@ -1377,6 +1653,7 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1390,6 +1667,8 @@
 		return DRM_ERR(EINVAL);
 	}
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t *)data,
 			     sizeof(vertex) );
 
@@ -1429,11 +1708,14 @@
 		buf->used = vertex.count; /* not used? */
 
 		if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-			radeon_emit_state( dev_priv,
-					   &sarea_priv->context_state,
-					   sarea_priv->tex_state,
-					   sarea_priv->dirty );
-			
+			if ( radeon_emit_state( dev_priv, filp_priv,
+						&sarea_priv->context_state,
+						sarea_priv->tex_state,
+						sarea_priv->dirty ) ) {
+				DRM_ERROR( "radeon_emit_state failed\n" );
+				return DRM_ERR( EINVAL );
+			}
+
 			sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
 					       RADEON_UPLOAD_TEX1IMAGES |
 					       RADEON_UPLOAD_TEX2IMAGES |
@@ -1461,6 +1743,7 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1475,6 +1758,8 @@
 		return DRM_ERR(EINVAL);
 	}
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t *)data,
 			     sizeof(elts) );
 
@@ -1523,10 +1808,13 @@
 	buf->used = elts.end;
 
 	if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-		radeon_emit_state( dev_priv,
-				   &sarea_priv->context_state,
-				   sarea_priv->tex_state,
-				   sarea_priv->dirty );
+		if ( radeon_emit_state( dev_priv, filp_priv,
+					&sarea_priv->context_state,
+					sarea_priv->tex_state,
+					sarea_priv->dirty ) ) {
+			DRM_ERROR( "radeon_emit_state failed\n" );
+			return DRM_ERR( EINVAL );
+		}
 
 		sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
 				       RADEON_UPLOAD_TEX1IMAGES |
@@ -1686,6 +1974,7 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1700,6 +1989,8 @@
 		return DRM_ERR(EINVAL);
 	}
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data,
 			     sizeof(vertex) );
 
@@ -1747,7 +2038,10 @@
 					     sizeof(state) ) )
 				return DRM_ERR(EFAULT);
 
-			radeon_emit_state2( dev_priv, &state );
+			if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) {
+				DRM_ERROR( "radeon_emit_state2 failed\n" );
+				return DRM_ERR( EINVAL );
+			}
 
 			laststate = prim.stateidx;
 		}
@@ -1784,6 +2078,7 @@
 
 static int radeon_emit_packets( 
 	drm_radeon_private_t *dev_priv,
+	drm_file_t *filp_priv,
 	drm_radeon_cmd_header_t header,
 	drm_radeon_cmd_buffer_t *cmdbuf )
 {
@@ -1798,8 +2093,15 @@
 	sz = packet[id].len;
 	reg = packet[id].start;
 
-	if (sz * sizeof(int) > cmdbuf->bufsz) 
+	if (sz * sizeof(int) > cmdbuf->bufsz) {
+		DRM_ERROR( "Packet size provided larger than data provided\n" );
 		return DRM_ERR(EINVAL);
+	}
+
+	if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) {
+		DRM_ERROR( "Packet verification failed\n" );
+		return DRM_ERR( EINVAL );
+	}
 
 	BEGIN_RING(sz+1);
 	OUT_RING( CP_PACKET0( reg, (sz-1) ) );
@@ -1882,24 +2184,21 @@
 
 
 static int radeon_emit_packet3( drm_device_t *dev,
+				drm_file_t *filp_priv,
 				drm_radeon_cmd_buffer_t *cmdbuf )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	int cmdsz, tmp;
-	int *cmd = (int *)cmdbuf->buf;
+	unsigned int cmdsz;
+	int *cmd = (int *)cmdbuf->buf, ret;
 	RING_LOCALS;
 
-
 	DRM_DEBUG("\n");
 
-	if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
-		return DRM_ERR(EFAULT);
-
-	cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
-	if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
-	    cmdsz * 4 > cmdbuf->bufsz)
-		return DRM_ERR(EINVAL);
+	if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+						     cmdbuf, &cmdsz ) ) ) {
+		DRM_ERROR( "Packet verification failed\n" );
+		return ret;
+	}
 
 	BEGIN_RING( cmdsz );
 	OUT_RING_USER_TABLE( cmd, cmdsz );
@@ -1912,27 +2211,25 @@
 
 
 static int radeon_emit_packet3_cliprect( drm_device_t *dev,
+					 drm_file_t *filp_priv,
 					 drm_radeon_cmd_buffer_t *cmdbuf,
 					 int orig_nbox )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_clip_rect_t box;
-	int cmdsz, tmp;
-	int *cmd = (int *)cmdbuf->buf;
+	unsigned int cmdsz;
+	int *cmd = (int *)cmdbuf->buf, ret;
 	drm_clip_rect_t *boxes = cmdbuf->boxes;
 	int i = 0;
 	RING_LOCALS;
 
 	DRM_DEBUG("\n");
 
-	if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
-		return DRM_ERR(EFAULT);
-
-	cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
-	if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
-	    cmdsz * 4 > cmdbuf->bufsz)
-		return DRM_ERR(EINVAL);
+	if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+						     cmdbuf, &cmdsz ) ) ) {
+		DRM_ERROR( "Packet verification failed\n" );
+		return ret;
+	}
 
 	if (!orig_nbox)
 		goto out;
@@ -2009,6 +2306,7 @@
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf = 0;
 	int idx;
@@ -2023,6 +2321,8 @@
 		return DRM_ERR(EINVAL);
 	}
 
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
 	DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data,
 			     sizeof(cmdbuf) );
 
@@ -2053,7 +2353,7 @@
 		switch (header.header.cmd_type) {
 		case RADEON_CMD_PACKET: 
 			DRM_DEBUG("RADEON_CMD_PACKET\n");
-			if (radeon_emit_packets( dev_priv, header, &cmdbuf )) {
+			if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
 				DRM_ERROR("radeon_emit_packets failed\n");
 				return DRM_ERR(EINVAL);
 			}
@@ -2096,7 +2396,7 @@
 
 		case RADEON_CMD_PACKET3:
 			DRM_DEBUG("RADEON_CMD_PACKET3\n");
-			if (radeon_emit_packet3( dev, &cmdbuf )) {
+			if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
 				DRM_ERROR("radeon_emit_packet3 failed\n");
 				return DRM_ERR(EINVAL);
 			}
@@ -2104,7 +2404,7 @@
 
 		case RADEON_CMD_PACKET3_CLIP:
 			DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
-			if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) {
+			if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
 				DRM_ERROR("radeon_emit_packet3_clip failed\n");
 				return DRM_ERR(EINVAL);
 			}
@@ -2212,5 +2512,33 @@
 		return DRM_ERR(EFAULT);
 	}
 	
+	return 0;
+}
+
+int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
+	drm_radeon_setparam_t sp;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR( EINVAL );
+	}
+
+	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
+	DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t* )data,
+				  sizeof( sp ) );
+
+	switch( sp.param ) {
+	case RADEON_SETPARAM_FB_LOCATION:
+		filp_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+		break;
+	default:
+		DRM_DEBUG( "Invalid parameter %d\n", sp.param );
+		return DRM_ERR( EINVAL );
+	}
+
 	return 0;
 }
diff -Nru a/drivers/char/drm/sis.h b/drivers/char/drm/sis.h
--- a/drivers/char/drm/sis.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/sis.h	Wed Apr 14 18:25:42 2004
@@ -62,6 +62,13 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_FREE)]	= { sis_ioctl_agp_free,	1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_INIT)]	= { sis_fb_init,	1, 1 }
 
+#define DRIVER_PCI_IDS							\
+	{0x1039, 0x0300, 0},						\
+	{0x1039, 0x5300, 0},						\
+	{0x1039, 0x6300, 0},						\
+	{0x1039, 0x7300, 0},						\
+	{0, 0, 0}
+
 #define __HAVE_COUNTERS		5
 
 /* Buffer customization:
diff -Nru a/drivers/char/drm/tdfx.h b/drivers/char/drm/tdfx.h
--- a/drivers/char/drm/tdfx.h	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/tdfx.h	Wed Apr 14 18:25:42 2004
@@ -39,4 +39,22 @@
 #define __HAVE_MTRR		1
 #define __HAVE_CTX_BITMAP	1
 
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
+
+#define DRIVER_NAME		"tdfx"
+#define DRIVER_DESC		"3dfx Banshee/Voodoo3+"
+#define DRIVER_DATE		"20010216"
+
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+#define DRIVER_PCI_IDS							\
+	{0x121a, 0x0003, 0},						\
+	{0x121a, 0x0004, 0},						\
+	{0x121a, 0x0005, 0},						\
+	{0x121a, 0x0007, 0},						\
+	{0x121a, 0x0009, 0},						\
+	{0, 0, 0}
+
 #endif
diff -Nru a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
--- a/drivers/char/drm/tdfx_drv.c	Wed Apr 14 18:25:42 2004
+++ b/drivers/char/drm/tdfx_drv.c	Wed Apr 14 18:25:42 2004
@@ -34,47 +34,6 @@
 #include "tdfx.h"
 #include "drmP.h"
 
-#define DRIVER_AUTHOR		"VA Linux Systems Inc."
-
-#define DRIVER_NAME		"tdfx"
-#define DRIVER_DESC		"3dfx Banshee/Voodoo3+"
-#define DRIVER_DATE		"20010216"
-
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		0
-#define DRIVER_PATCHLEVEL	0
-
-#ifndef PCI_VENDOR_ID_3DFX
-#define PCI_VENDOR_ID_3DFX 0x121A
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_VOODOO5
-#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_VOODOO4
-#define PCI_DEVICE_ID_3DFX_VOODOO4 0x0007
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_3000 /* Voodoo3 3000 */
-#define PCI_DEVICE_ID_3DFX_VOODOO3_3000 0x0005
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_2000 /* Voodoo3 3000 */
-#define PCI_DEVICE_ID_3DFX_VOODOO3_2000 0x0004
-#endif
-#ifndef PCI_DEVICE_ID_3DFX_BANSHEE
-#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003
-#endif
-
-static drm_pci_list_t DRM(idlist)[] = {
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_2000 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_3000 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO4 },
-	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5 },
-	{ 0, 0 }
-};
-
-#define DRIVER_CARD_LIST DRM(idlist)
-
-
 #include "drm_auth.h"
 #include "drm_bufs.h"
 #include "drm_context.h"