Index: Makefile
===================================================================
RCS file: /home/dcvs/dfports/x11/nvidia-driver/Makefile,v
retrieving revision 1.3
diff -u -r1.3 Makefile
--- Makefile	27 Feb 2004 17:21:33 -0000	1.3
+++ Makefile	15 Aug 2004 22:12:13 -0000
@@ -16,14 +16,14 @@
 		ftp://download1.nvidia.com/freebsd/1.0-${NVVERSION}/
 DISTNAME=	NVIDIA-FreeBSD-x86-${PORTVERSION:S/0./0-/}
 
-MAINTAINER=	danfe@regency.nsu.ru
+MAINTAINER=	coolvibe@hackerheaven.org
 COMMENT=	NVidia graphics card binary drivers for hardware OpenGL rendering
 
 USE_X_PREFIX=	yes
 NO_PACKAGE=	should be recompiled for a particular FreeBSD kernel
 INSTALLS_SHLIB=	yes
 
-NVVERSION=	4365
+NVVERSION=	6113
 
 .include <bsd.dfport.pre.mk>
 
@@ -39,19 +39,9 @@
 USE_LINUX=	yes
 .endif
 
-.if ${OSVERSION} < 470000
-IGNORE=		"requires FreeBSD -STABLE, version 4.7-RELEASE or later"
-.endif
-
-.if ${OSVERSION} < 500000
-PLIST_SUB+=	FREEBSD5="@comment " FREEBSD4=""
-.else
-PLIST_SUB+=	FREEBSD5="" FREEBSD4="@comment "
-.endif
-
 pre-everything::
-.if !defined(WITH_FREEBSD_AGP)
-	@${ECHO_MSG} "Define WITH_FREEBSD_AGP to use FreeBSD AGP GART driver"
+.if !defined(WITH_DRAGONFLY_AGP)
+	@${ECHO_MSG} "Define WITH_DRAGONFLY_AGP to use DragonFlyBSD AGP GART driver"
 .endif
 .if !defined(FORCE_AGP_RATE)
 	@${ECHO_MSG} "Define FORCE_AGP_RATE to limit the driver to lower speeds"
@@ -64,8 +54,8 @@
 USE_REINPLACE=	yes
 
 post-patch:
-. if defined(WITH_FREEBSD_AGP)
-	@${REINPLACE_CMD} "s/undef USE_OS_AGP_GART/define USE_OS_AGP_GART/" \
+. if defined(WITH_DRAGONFLY_AGP)
+	@${REINPLACE_CMD} "s/undef NV_SUPPORT_OS_AGP/define NV_SUPPORT_OS_AGP/" \
 		${WRKSRC}/src/nv-freebsd.h
 . endif
 . if defined(FORCE_AGP_RATE)
@@ -81,7 +71,7 @@
 	@${MKDIR} ${LINUXBASE}/usr/lib
 .endif
 	-@(kldstat -n linux || kldload linux)
-	-rm ${WRKSRC}/module/i386 # hack
+	-rm -f ${WRKSRC}/src/i386
 
 post-install:
 .if ${OSVERSION} < 500000
Index: distinfo
===================================================================
RCS file: /home/dcvs/dfports/x11/nvidia-driver/distinfo,v
retrieving revision 1.1
diff -u -r1.1 distinfo
--- distinfo	14 Oct 2003 00:01:43 -0000	1.1
+++ distinfo	15 Aug 2004 20:33:10 -0000
@@ -1 +1,2 @@
-MD5 (NVIDIA-FreeBSD-x86-1.0-4365.tar.gz) = e14d9f2668746ee4d8b47e1c9dbc78af
+MD5 (NVIDIA-FreeBSD-x86-1.0-6113.tar.gz) = 1dab16b9ebf3ab4253811b6ba29fc701
+SIZE (NVIDIA-FreeBSD-x86-1.0-6113.tar.gz) = 6215565
Index: files/patch-dfly
===================================================================
RCS file: /home/dcvs/dfports/x11/nvidia-driver/files/patch-dfly,v
retrieving revision 1.5
diff -u -r1.5 patch-dfly
--- files/patch-dfly	28 Jul 2004 06:11:39 -0000	1.5
+++ files/patch-dfly	15 Aug 2004 20:41:49 -0000
@@ -1,19 +1,28 @@
-diff -urN ./module/Makefile ../../nvidia-patched/module/Makefile
---- ./module/Makefile	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/module/Makefile	2004-07-21 10:14:32.000000000 +0200
-@@ -6,7 +6,7 @@
- KMOD=		nvidia
- SRCS=		nvidia_ctl.c nvidia_dev.c nvidia_linux.c nvidia_os.c nvidia_os_pci.c nvidia_os_registry.c nvidia_pci.c nvidia_subr.c nvidia_sysctl.c 
- SRCS+=		device_if.h bus_if.h pci_if.h vnode_if.h
--CFLAGS+=	-I${NVIDIA_ROOT}/src -D__KERNEL__ -DNV_MAJOR_VERSION=1 -DNV_MINOR_VERSION=0 -DNV_PATCHLEVEL=4365  -DNVCPU_X86   -DNV_BSD   -DNV_INT64_OK   -DNV_UNIX     
-+CFLAGS+=	-I${NVIDIA_ROOT}/src -D__KERNEL__ -DNV_MAJOR_VERSION=1 -DNV_MINOR_VERSION=0 -DNV_PATCHLEVEL=4365  -DNVCPU_X86   -DNV_BSD   -DNV_INT64_OK   -DNV_UNIX     -Werror
- NVOBJ=		${NVIDIA_ROOT}/obj/nv-kernel.o
- OBJS+=		NVIDIA.o
- NOOBJ=		true
-diff -urN ./src/nv-dragonfly.h ../../nvidia-patched/src/nv-dragonfly.h
---- ./src/nv-dragonfly.h	1970-01-01 01:00:00.000000000 +0100
-+++ ../../nvidia-patched/src/nv-dragonfly.h	2004-07-21 10:24:22.000000000 +0200
-@@ -0,0 +1,297 @@
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/Makefile.rej ./src/Makefile.rej
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/Makefile.rej	1970-01-01 01:00:00.000000000 +0100
++++ ./src/Makefile.rej	2004-08-04 21:26:57.000000000 +0200
+@@ -0,0 +1,17 @@
++***************
++*** 12,18 ****
++  SRCS=		nvidia_ctl.c nvidia_dev.c nvidia_linux.c nvidia_os.c nvidia_os_pci.c nvidia_os_registry.c nvidia_pci.c nvidia_subr.c nvidia_sysctl.c 
++  SRCS+=		device_if.h bus_if.h pci_if.h vnode_if.h
++  CFLAGS+=	-I${NVIDIA_ROOT}/src -DNV_MAJOR_VERSION=1 -DNV_MINOR_VERSION=0 -DNV_PATCHLEVEL=6108  -DNVCPU_X86  -DNV_BSD  -DNV_INT64_OK  -DNV_UNIX   
++- CFLAGS+=	-D__KERNEL__ -UDEBUG -U_DEBUG -DNDEBUG -O -fno-common
++  
++  OBJS+=		${RMOBJ}
++  NOOBJ=		true
++--- 12,18 ----
++  SRCS=		nvidia_ctl.c nvidia_dev.c nvidia_linux.c nvidia_os.c nvidia_os_pci.c nvidia_os_registry.c nvidia_pci.c nvidia_subr.c nvidia_sysctl.c 
++  SRCS+=		device_if.h bus_if.h pci_if.h vnode_if.h
++  CFLAGS+=	-I${NVIDIA_ROOT}/src -DNV_MAJOR_VERSION=1 -DNV_MINOR_VERSION=0 -DNV_PATCHLEVEL=6108  -DNVCPU_X86  -DNV_BSD  -DNV_INT64_OK  -DNV_UNIX   
+++ CFLAGS+=	-D__KERNEL__ -UDEBUG -U_DEBUG -DNDEBUG -O -fno-common -Werror
++  
++  OBJS+=		${RMOBJ}
++  NOOBJ=		true
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nv-dragonfly.h ./src/nv-dragonfly.h
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nv-dragonfly.h	1970-01-01 01:00:00.000000000 +0100
++++ ./src/nv-dragonfly.h	2004-08-04 21:26:57.000000000 +0200
+@@ -0,0 +1,360 @@
 +/* _NVRM_COPYRIGHT_BEGIN_
 + *
 + * Copyright 2001 by NVIDIA Corporation.  All rights reserved.  All
@@ -82,7 +91,7 @@
 +#include <vm/pmap.h>
 +#include <vm/vm_map.h>
 +
-+#include <dev/agp//agpvar.h>
++#include <dev/agp/agpvar.h>
 +#include <sys/agpio.h>
 +
 +#include "net/if.h"
@@ -92,12 +101,31 @@
 +#include <machine/smp.h>
 +#include <bus/pci/pcireg.h>
 +#include <bus/pci/pcivar.h>
++#include <sys/filedesc.h>
 +
 +#include <sys/thread2.h>
 +
++#ifdef PAE
++/* XXX Fix me? (PAE) */
++#error This driver does not support PAE enabled kernels!
++#endif
++
++#define CURTHREAD curthread
++
 +#define vm_page_lock_queues()
 +#define vm_page_unlock_queues()
 +
++#define vm_page_lock_queues()
++#define vm_page_unlock_queues()
++
++#define VM_OBJECT_LOCK(_obj)
++#define VM_OBJECT_UNLOCK(_obj)
++
++#define pmap_invalidate_range(_pmap, _sva, _eva) cpu_invltlb()
++
++#define pte_load(_ptep)        (*(_ptep))
++#define pte_store(_ptep, _pte) (*(_ptep) = (_pte))
++
 +/*
 + * The resource manager client tracking needs an identifier that uniquely
 + * represents a client connection across threads. It needs to be specific
@@ -106,9 +134,8 @@
 + * on FreeBSD, due to its thread-aware reference counting.
 + */
 +
-+#define __TD_FDT(td)     ((td)->td_proc->p_fd)
-+#define __TD_FDT_CNT(td) ((td)->td_proc->p_fd->fd_refcnt)
-+
++#define __TD_FDT(_td)     ((_td)->td_proc->p_fd)
++#define __TD_FDT_CNT(_td) ((_td)->td_proc->p_fd->fd_refcnt)
 +
 +/*
 + * The NVIDIA kernel module's malloc identifier, needed for both tracking
@@ -118,21 +145,23 @@
 +
 +MALLOC_DECLARE(M_NVIDIA);
 +
++
 +/*
-+ * This define controls if the module will be built to support the NVIDIA
-+ * AGP GART driver or the FreeBSD AGPGART driver module. If you decide to
-+ * use AGPGART, the agp.ko module must be preloaded from loader.conf.
++ * Enable/Disable support for FreeBSD's AGP GART driver. Please note that
++ * agp.ko may need to be preloaded from loader.conf; this define does not
++ * influence support for NVIDIA's builtin AGP GART driver.
 + */
 +
-+#undef USE_OS_AGP_GART
++#undef NV_SUPPORT_OS_AGP
 +
 +/*
-+ * This flag determines if system memory for use with the NVIDIA AGP GART
-+ * driver is allocated as a contiguous block of kernel virtual memory, or
-+ * as a VM object. The latter is better (tm), and thus the default.
++ * Decides if the FreeBSD kernel's vm86 interface is used for int10 calls
++ * to the video BIOS. Since Linux does not offer this functionality, we
++ * also disable it here by default; this minimizes behavioral differences
++ * between the two platforms.
 + */
 +
-+#define NV_AGP_USE_VM_OBJECT 1
++#undef NV_USE_OS_VM86_INT10CALL
 +
 +/*
 + * This option decides if the driver will be built with support for Linux
@@ -140,7 +169,15 @@
 + * no need for Linux 3D applications, you can safely unset this flag.
 + */
 +
-+#define NV_SUPPORT_LINUX_COMPAT 1
++#define NV_SUPPORT_LINUX_COMPAT
++
++/*
++ * Enable/Disable support for ACPI Power Management. This is untested and
++ * thus disabled by default (this is 5.x/-CURRENT only).
++ */
++
++#undef NV_SUPPORT_ACPI_PM
++
 +
 +/*
 + * The DMA memory allocation tracking structure. DMA memory alloctions on
@@ -157,9 +194,16 @@
 +    vm_offset_t address;
 +    u_int32_t offset;
 +    struct vm_object *object;
++    vm_offset_t *pte;
 +} nv_alloc_t;
 +
 +typedef
++struct nv_os_event {
++    STAILQ_ENTRY(nv_os_event) queue;
++    nv_event_t event;
++} nv_os_event_t;
++
++typedef
 +struct nv_alloc_private {
 +    u_int32_t count;
 +    u_int32_t alloc_type_contiguous;
@@ -175,34 +219,38 @@
 +
 +    struct resource *reg;
 +    int reg_rid;
-+    int reg_type;
 +
 +    struct resource *mem;
 +    int mem_rid;
-+    int mem_type;
 +
 +    struct resource *irq;
 +    void *irq_ih;
 +    int   irq_rid;
 +
++    struct resource *iop;
++    int iop_rid;
++
++    bus_space_handle_t bs_handle;
++    bus_space_tag_t bs_tag;
++
 +    dev_t cdev;
 +    nv_state_t *nv_state;
 +
++    /* queue of os events */
++    STAILQ_HEAD(event_queue, nv_os_event) event_queue;
++
 +    struct sysctl_ctx_list sysctl_ctx;
 +    struct selinfo rsel;
 +
-+    struct callout timer_ch;
++    struct callout_handle timer_ch;
 +
 +    /* list of allocations */
 +    SLIST_HEAD(alloc_list, nv_alloc) alloc_list;
 +
-+#if __FreeBSD_version >= 500000
-+    struct mtx mtx_rm;
-+    struct mtx mtx_api;
-+#else
++    int refcnt;
++
 +    int spl;
 +    struct lock api_lock;
-+#endif
 +} nvidia_softc_t;
 +
 +
@@ -227,6 +275,17 @@
 +
 +extern nv_parm_t nv_parms[];
 +
++/*
++ * These macros extract the encoded ioctl type and number from the
++ * command; we inspect the type to verify that device/control ioctls
++ * originate from NVIDIA RM clients and use the number to allow the
++ * core resource manager's ioctl handler to be ignorant of operating
++ * specific ioctl encodings.
++ */
++
++#define __NV_IOC_TYPE(_cmd) (((_cmd) >> 8) & 0xff)
++#define __NV_IOC_NR(_cmd)   (((_cmd) >> 0) & 0xff)
++
 +
 +/* nvidia_dev.c */
 +int    nvidia_dev_attach     (struct nvidia_softc *);
@@ -236,13 +295,27 @@
 +int    nvidia_ctl_attach     (void);
 +int    nvidia_ctl_detach     (void);
 +
++/* nvidia_pci.c */
++int    nvidia_pci_setup_intr     (device_t dev);
++int    nvidia_pci_teardown_intr  (device_t dev);
++void   nvidia_pci_enable_device  (device_t dev);
++
++#define NV_PCI_ENABLE_DEVICE(_nv)                       \
++  ({                                                    \
++       struct nvidia_softc *__sc;                       \
++       if (((_nv)->flags & NV_FLAG_CONTROL) == 0) {     \
++           __sc = (_nv)->os_state;                      \
++           nvidia_pci_enable_device(__sc->dev);         \
++       }                                                \
++  })
++
 +/* nvidia_subr.c */
 +int    nvidia_attach         (device_t);
 +int    nvidia_detach         (device_t);
 +int    nvidia_suspend        (device_t);
 +int    nvidia_resume         (device_t);
 +int    nvidia_alloc          (device_t);
-+int    nvidia_free           (device_t);
++void   nvidia_free           (device_t);
 +void   nvidia_intr           (void *);
 +int    nvidia_modevent       (module_t, int, void *);
 +
@@ -251,41 +324,40 @@
 +void   nv_lock_api           (nv_state_t *);
 +void   nv_unlock_api         (nv_state_t *);
 +
-+S032   nv_alloc_contig_pages (nv_state_t *, VOID **, U032);
-+S032   nv_free_contig_pages  (nv_state_t *, VOID *);
-+S032   nv_alloc_system_pages (nv_state_t *, VOID **, U032);
-+S032   nv_free_system_pages  (nv_state_t *, VOID *);
++S032   nv_alloc_contig_pages (nv_state_t *, void **, U032);
++S032   nv_free_contig_pages  (nv_state_t *, void *);
++S032   nv_alloc_system_pages (nv_state_t *, void **, U032);
++S032   nv_free_system_pages  (nv_state_t *, void *);
 +
-+S032   nv_alloc_vm_object    (nv_state_t *, VOID **, U032);
-+S032   nv_free_vm_object     (nv_state_t *, VOID *);
++S032   nv_alloc_vm_object    (nv_state_t *, void **, U032);
++S032   nv_free_vm_object     (nv_state_t *, void *);
 +
 +void*  nv_find_alloc         (nv_state_t *, vm_offset_t);
 +void*  nv_find_alloc_obj     (nv_state_t *, vm_offset_t);
 +
-+S032   nv_os_agp_init        (nv_state_t *, VOID **, VOID **, U032 *);
++S032   nv_os_agp_init        (nv_state_t *, void **, void **, U032 *);
 +S032   nv_os_agp_teardown    (nv_state_t *);
-+S032   nv_alloc_agp_pages    (nv_state_t *, VOID **, U032, U032, VOID **);
-+S032   nv_free_agp_pages     (nv_state_t *, VOID **, U032, VOID *);
++S032   nv_alloc_agp_pages    (nv_state_t *, void **, U032, U032, void **);
++S032   nv_free_agp_pages     (nv_state_t *, void **, U032, void *);
 +
 +/* nvidia_sysctl.c */
 +void   nvidia_sysctl_init    (void);
 +void   nvidia_sysctl_exit    (void);
 +
-+U008   nvidia_find_cap       (device_t);
-+void*  nvidia_find_bridge    (void);
-+
-+int    nvidia_sysctl_vbios   (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_type    (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_rates   (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_fw      (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_sba     (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_regs    (SYSCTL_HANDLER_ARGS);
-+
-+int    nvidia_sysctl_driver  (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_rate_s  (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_fw_s    (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_sba_s   (SYSCTL_HANDLER_ARGS);
-+int    nvidia_sysctl_status  (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_dev_model  (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_dev_vbios  (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_bus_type   (SYSCTL_HANDLER_ARGS);
++
++int    nvidia_sysctl_agp_rates      (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_agp_fw         (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_agp_sba        (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_agp_registers  (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_agp_driver     (SYSCTL_HANDLER_ARGS);
++
++int    nvidia_sysctl_agp_status       (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_agp_rate_status  (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_agp_fw_status    (SYSCTL_HANDLER_ARGS);
++int    nvidia_sysctl_agp_sba_status   (SYSCTL_HANDLER_ARGS);
 +
 +void   nv_sysctl_init        (nv_state_t *);
 +void   nv_sysctl_exit        (nv_state_t *);
@@ -296,7 +368,7 @@
 +void   nvidia_linux_exit     (void);
 +
 +/* ioctl helpers */
-+int    nvidia_set_primary     (struct nv_ioctl_primary_card *);
++int    nvidia_post_vbios      (struct nv_ioctl_post_vbios *);
 +int    nvidia_get_card_info   (struct nv_ioctl_card_info *);
 +int    nvidia_get_api_version (struct nv_ioctl_rm_api_version *);
 +int    nvidia_handle_ioctl    (dev_t, u_long, caddr_t, int, d_thread_t *);
@@ -311,503 +383,2095 @@
 +
 +#endif /* __NV_DRAGONFLY_H */
 +
-diff -urN ./src/nvidia_ctl.c ../../nvidia-patched/src/nvidia_ctl.c
---- ./src/nvidia_ctl.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_ctl.c	2004-07-21 10:14:32.000000000 +0200
-@@ -11,7 +11,11 @@
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_ctl.c ./src/nvidia_ctl.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_ctl.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_ctl.c	2004-08-04 21:26:57.000000000 +0200
+@@ -11,7 +11,8 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else
+-#include "nv-freebsd.h"
++
 +#include "nv-dragonfly.h"
-+#endif
  
  static d_open_t  nvidia_ctl_open;
  static d_close_t nvidia_ctl_close;
-@@ -19,7 +23,7 @@
+@@ -19,38 +20,22 @@
  static d_poll_t  nvidia_ctl_poll;
  
  static struct cdevsw nvidia_ctl_cdevsw = {
 -#if __FreeBSD_version < 500105
-+#if __FreeBSD_version < 500105 && !defined(__DragonFly__)
-     /* open    */  nvidia_ctl_open,
-     /* close */    nvidia_ctl_close,
-     /* read */     noread,
-@@ -37,7 +41,7 @@
-     /* bmaj */     -1,
- #endif
-     /* kqfilter */ NULL,
+-    /* open    */  nvidia_ctl_open,
+-    /* close */    nvidia_ctl_close,
+-    /* read */     noread,
+-    /* write */    nowrite,
+-    /* ioctl */    nvidia_ctl_ioctl,
+-    /* poll */     nvidia_ctl_poll,
+-    /* mmap */     nommap,
+-    /* strategy */ nostrategy,
+-    /* name */     "nvidiactl",
+-    /* maj */      CDEV_MAJOR,
+-    /* dump */     nodump,
+-    /* psize */    nopsize,
+-    /* flags */    D_TRACKCLOSE,
+-#if __FreeBSD_version < 500000
+-    /* bmaj */     -1,
+-#endif
+-    /* kqfilter */ NULL,
 -#else
-+#elif !defined(__DragonFly__)
-     .d_open =      nvidia_ctl_open,
-     .d_close =     nvidia_ctl_close,
-     .d_ioctl =     nvidia_ctl_ioctl,
-@@ -46,6 +50,25 @@
-     .d_maj =       CDEV_MAJOR,
-     .d_flags =     D_TRACKCLOSE
- #endif
-+
-+/* Dragonfly */
-+#if defined(__DragonFly__)
-+    /* name */    "nvidiactl",
-+    /* maj */     CDEV_MAJOR,
-+    /* flags */    D_TRACKCLOSE,
-+    /* port */     NULL,
-+    /* autoq */    0,
-+
-+    /* open    */  nvidia_ctl_open,
-+    /* close */    nvidia_ctl_close,
-+    /* read */     noread,
-+    /* write */    nowrite,
-+    /* ioctl */    nvidia_ctl_ioctl,
-+    /* poll */     nvidia_ctl_poll,
-+    /* mmap */     nommap,
-+    /* strategy */ nostrategy,
-+    /* dump */     nodump,
-+#endif
+-    .d_open =      nvidia_ctl_open,
+-    .d_close =     nvidia_ctl_close,
+-    .d_ioctl =     nvidia_ctl_ioctl,
+-    .d_poll =      nvidia_ctl_poll,
+-    .d_name =      "nvidiactl",
+-#if __FreeBSD_version >= 502103
+-    .d_version =   D_VERSION,
+-    .d_flags =     D_TRACKCLOSE|D_NEEDGIANT
+-#else
+-    .d_maj =       CDEV_MAJOR,
+-    .d_flags =     D_TRACKCLOSE
+-#endif /* XXX Fix me? (fbsd version) */
+-#endif
++	/* name  */	"nvidiactl",
++	/* maj   */	CDEV_MAJOR,
++	/* flags */	D_TRACKCLOSE,
++	/* port  */	NULL,
++	/* autoq */	0,
++
++	/* open  */	nvidia_ctl_open,
++	/* close */	nvidia_ctl_close,
++	/* read  */	noread,
++	/* write */	nowrite,
++	/* ioctl */	nvidia_ctl_ioctl,
++	/* poll  */	nvidia_ctl_poll,
++	/* mmap  */	nommap,
++	/* strategy */	nostrategy,
++	/* dump  */	nodump,
++	/* psize */	nopsize,	
  };
  
  static dev_t          nvidia_ctl_cdev;
-@@ -200,16 +223,20 @@
-     struct nvidia_softc *sc;
- 
-     if (nvidia_count == 0) {
-+
-+
-         /*
-          * This routine is called from nvidia_attach, multiple times when
+@@ -204,6 +189,11 @@
           * more than one device is installed - this makes it necessary to
           * prevent multiple calls to make_dev.
           */
-+	cdevsw_add(&nvidia_ctl_cdevsw, -1, 255); /* XXX */
++
++	cdevsw_add(&nvidia_ctl_cdevsw, -1, 255); /* XXX is this correct? */
++
++	printf("cdevsw_add called for %s\n", nvidia_ctl_cdevsw.d_name);
++
          nvidia_ctl_cdev = make_dev(&nvidia_ctl_cdevsw,
                  CDEV_CTL_MINOR,
                  UID_ROOT, GID_WHEEL, 0666,
-                 "%s", nvidia_ctl_cdevsw.d_name);
- 
-+
-         sc = &nvidia_ctl_sc;
+@@ -213,15 +203,11 @@
          bzero(sc, sizeof(nvidia_softc_t));
          nvidia_ctl_state.os_state = sc;
-@@ -218,7 +245,7 @@
-         mtx_init(&sc->mtx_api, "ctl.mtx_api", NULL, MTX_DEF);
-         mtx_init(&sc->mtx_rm,  "ctl.mtx_rm",  NULL, MTX_SPIN);
- #else
--        lockinit(&sc->api_lock, PZERO, "ctl.api_lock", 0, 0); 
-+        lockinit(&sc->api_lock, 0, "ctl.api_lock", 0, 0); 
- #endif
+ 
+-#if __FreeBSD_version >= 500000
+-        mtx_init(&sc->mtx_rm, "ctl.mtx_rm", NULL, MTX_SPIN | MTX_RECURSE);
+-#endif
+-
+         /*
+          * Assume that none of the API paths are reentrant and
+          * that any could could conceivably sleep.
+          */
+-        lockinit(&sc->api_lock, PZERO | PCATCH, "ctl.api_lock", 0, 0); 
++        lockinit(&sc->api_lock, 0 | PCATCH, "ctl.api_lock", 0, 0); 
      }
  
-@@ -242,10 +269,17 @@
- #if __FreeBSD_version >= 500000
-         mtx_destroy(&sc->mtx_rm);
-         mtx_destroy(&sc->mtx_api);
--#else
-+#elif defined(__FreeBSD__) && !defined(__DragonFly__)
-         lockmgr(&sc->api_lock, LK_DRAIN, 0, curproc);
+     nvidia_count++;
+@@ -241,12 +227,16 @@
+          * the device reference count to prevent premature destruction of
+          * the control device.
+          */
+-#if __FreeBSD_version >= 500000
+-        mtx_destroy(&sc->mtx_rm);
 -#endif
-         destroy_dev(nvidia_ctl_cdev);
-+#else 
-+        lockmgr(&sc->api_lock, LK_DRAIN, NULL, curthread);
-+#endif
+         lockmgr(&sc->api_lock, LK_DRAIN, 0, CURTHREAD);
+ 
++	cdevsw_remove(&nvidia_ctl_cdevsw, -1, 255); /* XXX is this correct? */
 +
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
-+	cdevsw_remove(&nvidia_ctl_cdevsw, -1, 255); /* XXX */
++	printf("cdevsw_remove called for nvidiactl\n");
++
++#if 0	/* we shouldn't need destroy_dev anymore */
+         destroy_dev(nvidia_ctl_cdev);
 +#endif
 +
      }
  
      return 0;
-diff -urN ./src/nvidia_dev.c ../../nvidia-patched/src/nvidia_dev.c
---- ./src/nvidia_dev.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_dev.c	2004-07-21 10:14:32.000000000 +0200
-@@ -11,7 +11,11 @@
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_dev.c ./src/nvidia_dev.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_dev.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_dev.c	2004-08-04 21:26:57.000000000 +0200
+@@ -11,7 +11,7 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else 
+-#include "nv-freebsd.h"
 +#include "nv-dragonfly.h"
-+#endif
  
  static d_open_t  nvidia_dev_open;
  static d_close_t nvidia_dev_close;
-@@ -20,7 +24,7 @@
+@@ -20,39 +20,22 @@
  static d_mmap_t  nvidia_dev_mmap;
  
  static struct cdevsw nvidia_dev_cdevsw = {
 -#if __FreeBSD_version < 500105
-+#if __FreeBSD_version < 500105 && !defined(__DragonFly__)
-     /* open    */  nvidia_dev_open,
-     /* close */    nvidia_dev_close,
-     /* read */     noread,
-@@ -38,7 +42,7 @@
-     /* bmaj */     -1,
- #endif
-     /* kqfilter */ NULL,
+-    /* open    */  nvidia_dev_open,
+-    /* close */    nvidia_dev_close,
+-    /* read */     noread,
+-    /* write */    nowrite,
+-    /* ioctl */    nvidia_dev_ioctl,
+-    /* poll */     nvidia_dev_poll,
+-    /* mmap */     nvidia_dev_mmap,
+-    /* strategy */ nostrategy,
+-    /* name */     "nvidia",
+-    /* maj */      CDEV_MAJOR,
+-    /* dump */     nodump,
+-    /* psize */    nopsize,
+-    /* flags */    D_MEM|D_TRACKCLOSE,
+-#if __FreeBSD_version < 500000
+-    /* bmaj */     -1,
+-#endif
+-    /* kqfilter */ NULL,
 -#else
-+#elif !defined(__DragonFly__)
-     .d_open =      nvidia_dev_open,
-     .d_close =     nvidia_dev_close,
-     .d_ioctl =     nvidia_dev_ioctl,
-@@ -48,6 +52,26 @@
-     .d_maj =       CDEV_MAJOR,
-     .d_flags =     D_MEM|D_TRACKCLOSE
- #endif
-+
-+#ifdef __DragonFly__
-+    /* name */     "nvidia",
-+    /* maj */      CDEV_MAJOR,
-+    /* flags */    D_MEM|D_TRACKCLOSE,
-+    /* port */    NULL,
-+    /* autoq */    0,
-+
-+    /* open    */  nvidia_dev_open,
-+    /* close */    nvidia_dev_close,
-+    /* read */     noread,
-+    /* write */    nowrite,
-+    /* ioctl */    nvidia_dev_ioctl,
-+    /* poll */     nvidia_dev_poll,
-+    /* mmap */     nvidia_dev_mmap,
-+    /* strategy */ nostrategy,
-+    /* dump */     nodump,
-+    /* psize */    nopsize,
-+#endif
-+
+-    .d_open =      nvidia_dev_open,
+-    .d_close =     nvidia_dev_close,
+-    .d_ioctl =     nvidia_dev_ioctl,
+-    .d_poll =      nvidia_dev_poll,
+-    .d_mmap =      nvidia_dev_mmap,
+-    .d_name =      "nvidia",
+-#if __FreeBSD_version >= 502103
+-    .d_version =   D_VERSION,
+-    .d_flags =     D_MEM|D_TRACKCLOSE|D_NEEDGIANT
+-#else
+-    .d_maj =       CDEV_MAJOR,
+-    .d_flags =     D_MEM|D_TRACKCLOSE
+-#endif /* XXX Fix me? (fbsd version) */
+-#endif
++	/* name  */     "nvidia",
++	/* maj   */     CDEV_MAJOR,
++	/* flags */     D_MEM | D_TRACKCLOSE,
++	/* port  */     NULL,
++	/* autoq */     0,
++
++	/* open  */     nvidia_dev_open,
++	/* close */     nvidia_dev_close,
++	/* read  */     noread,
++	/* write */     nowrite,
++	/* ioctl */     nvidia_dev_ioctl,
++	/* poll  */     nvidia_dev_poll,
++	/* mmap  */     nvidia_dev_mmap,
++	/* strategy */  nostrategy,
++	/* dump  */     nodump,
++	/* psize */	nopsize,
  };
  
  int nvidia_dev_open(
-@@ -187,6 +211,7 @@
+@@ -166,9 +149,6 @@
+ int nvidia_dev_mmap(
+     dev_t dev,
+     vm_offset_t offset,
+-#if __FreeBSD_version >= 500102
+-    vm_offset_t *address,
+-#endif
+     int nprot
+ )
+ {
+@@ -187,19 +167,7 @@
+     nv_unlock_api(nv);
+ 
+     if (status != -1) {
+-#if __FreeBSD_version >= 500102
+-        /*
+-         * Return the actual physical address corresponding to the offset
+-         * to the caller.
+-         */
+-        *address = physical;
+-#else
+-        /*
+-         * Return the page frame number on older kernels. Lookup failures
+-         * will result in a negative error code for both cases.
+-         */
+         return atop(physical);
+-#endif
+     }
+ 
+     return status;
+@@ -207,6 +175,9 @@
  
- int nvidia_dev_attach (struct nvidia_softc *sc)
+ int nvidia_dev_attach(struct nvidia_softc *sc)
  {
 +    cdevsw_add(&nvidia_dev_cdevsw, -1, device_get_unit(sc->dev));
++    printf("cdevsw_add called for %s%d\n", nvidia_dev_cdevsw.d_name, device_get_unit(sc->dev));
++
      sc->cdev = make_dev(&nvidia_dev_cdevsw,
                  device_get_unit(sc->dev),
                  UID_ROOT, GID_WHEEL, 0666,
-@@ -199,7 +224,11 @@
+@@ -219,7 +190,12 @@
  
- int nvidia_dev_detach (struct nvidia_softc *sc)
+ int nvidia_dev_detach(struct nvidia_softc *sc)
  {
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
-     destroy_dev(sc->cdev);
-+#else
++    
 +    cdevsw_remove(&nvidia_dev_cdevsw, -1, device_get_unit(sc->dev));
++#if 0	/* we shouldn't need destroy_dev anymore */
+     destroy_dev(sc->cdev);
 +#endif
++
      return 0;
  }
  
-diff -urN ./src/nvidia_linux.c ../../nvidia-patched/src/nvidia_linux.c
---- ./src/nvidia_linux.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_linux.c	2004-07-21 10:14:32.000000000 +0200
-@@ -11,7 +11,11 @@
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_linux.c ./src/nvidia_linux.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_linux.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_linux.c	2004-08-04 21:26:57.000000000 +0200
+@@ -11,7 +11,7 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else
+-#include "nv-freebsd.h"
 +#include "nv-dragonfly.h"
-+#endif
  
  #define LINUX_IOCTL_NVIDIA_MIN 0x4600
  #define LINUX_IOCTL_NVIDIA_MAX 0x46ff
-@@ -33,7 +37,11 @@
+@@ -33,7 +33,7 @@
       * copy the user data in/out correctly.
       */
  
-+#ifndef __DragonFly__
-     return (ioctl(td, (struct ioctl_args *) args));
-+#else 
+-    return (ioctl(td, (struct ioctl_args *) args));
 +    return (ioctl((struct ioctl_args *) args));
-+#endif
  }
  
  struct linux_ioctl_handler nvidia_handler = {
-diff -urN ./src/nvidia_os.c ../../nvidia-patched/src/nvidia_os.c
---- ./src/nvidia_os.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_os.c	2004-07-21 10:24:00.000000000 +0200
-@@ -11,7 +11,11 @@
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_os.c ./src/nvidia_os.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_os.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_os.c	2004-08-04 21:27:27.000000000 +0200
+@@ -11,13 +11,13 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else
+-#include "nv-freebsd.h"
 +#include "nv-dragonfly.h"
-+#endif
  
  
  /*
-@@ -94,7 +98,11 @@
-     U032 size
+  * The NVIDIA kernel module's malloc identifier, needed for both tracking
+  * and actual allocation/freeing purposes. M_NVIDIA is declared elsewhere
+- * to make it known to other parts of the kernel module (nv-freebsd.h).
++ * to make it known to other parts of the kernel module (nv-dragonfly.h).
+  */
+ 
+ MALLOC_DEFINE(M_NVIDIA, "nvidia", "NVIDIA memory allocations");
+@@ -263,25 +263,26 @@
+     U032 mode
  )
  {
-+#ifndef __DragonFly__
-     *address = malloc(size, M_NVIDIA, M_NOWAIT|M_ZERO);
-+#else 
-+    *address = malloc(size, M_NVIDIA, M_WAITOK|M_ZERO);
-+#endif
-     return *address ? RM_OK : RM_ERROR;
- }
- 
-@@ -164,7 +172,7 @@
+-    void *vm;
+-    vm_offset_t va, vt;
+-    pt_entry_t *pte;
+-
+-    vm = pmap_mapdev(start, size);
+-
+-    if (vm != NULL && mode == NV_MEMORY_UNCACHED) {
+-        va = vt = (vm_offset_t) vm;
+-        do {
+-            pte = vtopte(vt);
+-            pte_store(pte, pte_load(pte) | PG_N);
+-            vt += PAGE_SIZE;
+-        } while (vt < va + size);
++	void *vm;
++	vm_offset_t va, vt;
++	pt_entry_t *pte;
++
++	vm = pmap_mapdev(start, size);
++
++	if (vm != NULL && mode == NV_MEMORY_UNCACHED) {
++		va = vt = (vm_offset_t) vm;
++		do {
++			pte = vtopte(vt);
++			pte_store(pte, pte_load(pte) | PG_N);
++			vt += PAGE_SIZE;
++		} while (vt < va + size);
+ 
+-        pmap_invalidate_range(kernel_pmap, va, vt);
+-    }
++		pmap_invalidate_range(kernel_pmap, va, vt);
++	}
++
++	/* XXX Fix me! (x86 only) */
++	return vm;
  
- BOOL os_is_administrator(PHWINFO pDev)
- {
--#if __FreeBSD_version < 500000
-+#if __FreeBSD_version < 500000 && !defined(__DragonFly__)
-     return suser(curproc);
- #else
-     return suser(curthread);
-@@ -301,7 +309,11 @@
-             *pte |= PG_N;
-             va += PAGE_SIZE;
-         } while (va < (vm_offset_t) vm + size);
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
-         invltlb();
-+#else /* DragonFly BSD */
-+	cpu_invltlb();
-+#endif
-     }
+-    /* XXX Fix me! (x86 only) */
+-    return vm;
+ }
  
-     return vm;
-@@ -561,8 +573,13 @@
-      * XXX We need opt_global.h for the SMP and APIC_IO #define(s), which
-      * is in ../../compile/SYSTEM_NAME (see config(8)). How do we get it?
+ void os_unmap_kernel_space(
+@@ -567,7 +568,7 @@
+      * Assume that none of the API paths are reentrant and
+      * that any could could conceivably sleep.
       */
-+#if !defined(__DragonFly__)
-     return mp_ncpus;
- #else
-+    return ncpus;
-+#endif
-+
-+#else
-     return 1; /* single processor system */
- #endif
- }
-diff -urN ./src/nvidia_os_pci.c ../../nvidia-patched/src/nvidia_os_pci.c
---- ./src/nvidia_os_pci.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_os_pci.c	2004-07-21 10:14:32.000000000 +0200
-@@ -11,7 +11,11 @@
+-    lockinit(&mtx->mutex_lock, PZERO | PCATCH, "rm.mutex_lock", 0, 0);
++    lockinit(&mtx->mutex_lock, 0 | PCATCH, "rm.mutex_lock", 0, 0);
+ 
+     mtx->refcnt = 1;
+     *semaphore = (void *) mtx;
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_os_pci.c ./src/nvidia_os_pci.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_os_pci.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_os_pci.c	2004-08-04 21:26:57.000000000 +0200
+@@ -11,7 +11,7 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else
+-#include "nv-freebsd.h"
 +#include "nv-dragonfly.h"
-+#endif
  
  
- VOID* os_pci_init_handle(
-diff -urN ./src/nvidia_os_registry.c ../../nvidia-patched/src/nvidia_os_registry.c
---- ./src/nvidia_os_registry.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_os_registry.c	2004-07-21 10:14:32.000000000 +0200
-@@ -11,7 +11,11 @@
+ void* os_pci_init_handle(
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_os_registry.c ./src/nvidia_os_registry.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_os_registry.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_os_registry.c	2004-08-04 21:26:57.000000000 +0200
+@@ -11,7 +11,7 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else
+-#include "nv-freebsd.h"
 +#include "nv-dragonfly.h"
-+#endif
  
  
  /*
-diff -urN ./src/nvidia_pci.c ../../nvidia-patched/src/nvidia_pci.c
---- ./src/nvidia_pci.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_pci.c	2004-07-21 10:14:32.000000000 +0200
-@@ -11,7 +11,11 @@
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_pci.c ./src/nvidia_pci.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_pci.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_pci.c	2004-08-04 21:26:57.000000000 +0200
+@@ -11,7 +11,7 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else
+-#include "nv-freebsd.h"
 +#include "nv-dragonfly.h"
-+#endif
  
- #define NVIDIA_VENDORID 0x10de
- #define NVIDIA_PCI_REG  0x10
-@@ -95,8 +99,10 @@
- #if __FreeBSD_version >= 500000
-     mtx_init(&sc->mtx_api, "dev.mtx_api", NULL, MTX_DEF);
-     mtx_init(&sc->mtx_rm,  "dev.mtx_rm",  NULL, MTX_SPIN);
--#else
-+#elif !defined(__DragonFly__)
-     lockinit(&sc->api_lock, PZERO, "dev.api_lock", 0, 0); 
-+#else
-+    lockinit(&sc->api_lock, 0, "dev.api_lock", 0, 0); 
- #endif
-     return 0;
+ #define NVIDIA_PCI_REG_RID  0x10
+ #define NVIDIA_PCI_MEM_RID  0x14
+@@ -147,15 +147,11 @@
+         goto fail;
+     }
  
-@@ -114,8 +120,10 @@
- #if __FreeBSD_version >= 500000
-     mtx_destroy(&sc->mtx_rm);
-     mtx_destroy(&sc->mtx_api);
--#else
-+#elif !defined(__DragonFly__)
-     lockmgr(&sc->api_lock, LK_DRAIN, 0, curproc);
-+#else
-+    lockmgr(&sc->api_lock, LK_DRAIN, NULL, curthread);
- #endif
+-#if __FreeBSD_version >= 500000
+-    mtx_init(&sc->mtx_rm, "dev.mtx_rm", NULL, MTX_SPIN | MTX_RECURSE);
+-#endif
+-
+     /*
+      * Assume that none of the API paths are reentrant and
+      * that any could could conceivably sleep.
+      */
+-    lockinit(&sc->api_lock, PZERO | PCATCH, "dev.api_lock", 0, 0); 
++    lockinit(&sc->api_lock, 0 | PCATCH, "dev.api_lock", 0, 0); 
+ 
+     return 0;
  
-     status = nvidia_detach(dev);
-diff -urN ./src/nvidia_subr.c ../../nvidia-patched/src/nvidia_subr.c
---- ./src/nvidia_subr.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_subr.c	2004-07-21 10:27:21.000000000 +0200
-@@ -11,7 +11,11 @@
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_subr.c ./src/nvidia_subr.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_subr.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_subr.c	2004-08-04 21:34:46.000000000 +0200
+@@ -11,7 +11,7 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else
+-#include "nv-freebsd.h"
 +#include "nv-dragonfly.h"
-+#endif
  
  
  devclass_t nvidia_devclass;
-@@ -51,15 +55,21 @@
-         return status;
+@@ -28,6 +28,8 @@
+     sc = device_get_softc(dev);
+     nv = sc->nv_state;
  
-     nv_sysctl_init(nv);
++    printf("nvidia_attach() called - state flags %d\n", nv->flags);
 +
-+    callout_init(&sc->timer_ch);
-+    
-     return 0;
- }
+     nv->os_state         = sc;
+     nv->flags            = 0;
+     nv->device_number    = device_get_unit(dev);
+@@ -683,18 +685,6 @@
  
- int nvidia_detach(device_t dev)
+ void nv_lock_rm(nv_state_t *nv)
  {
-     int status;
--    struct nvidia_softc *sc;
-+    struct nvidia_softc *sc; /* gcc is a whiny bitch */
- 
-     sc = device_get_softc(dev);
-+
+-#if __FreeBSD_version >= 500000
+-    /*
+-     * With SMPng, the "giant" kernel lock is gone. That means that we're
+-     * in a more complex enviroment locking-wise, but since the necessary
+-     * locking primitives are available to us, we can handle it.
+-     *
+-     * With mtx_lock_spin we acquire a spin mutex and locally disable all
+-     * interrupts on the current processor.
+-     */
+-    struct nvidia_softc *sc = nv->os_state;
+-    mtx_lock_spin(&sc->mtx_rm);
+-#else
+     /* 
+      * While SMP configurations are handled with a global kernel lock and
+      * in such a way that only one of the CPUs is executing a process and
+@@ -704,28 +694,16 @@
+      * This "lock" thus disables interrupts for the duration of this code
+      * segment's execution.
+      */
+-    struct nvidia_softc *sc = nv->os_state;
+-    sc->spl = splhigh();
+-#endif
 +    crit_enter();
-+    callout_stop(&sc->timer_ch); /* just in case */
-     nv_sysctl_exit(sc->nv_state);
- 
-     if ((status = nvidia_dev_detach(sc)) != 0)
-@@ -67,6 +77,7 @@
+ }
  
-     if ((status = nvidia_ctl_detach()) != 0)
-         return status;
+ void nv_unlock_rm(nv_state_t *nv)
+ {
+-#if __FreeBSD_version >= 500000
+-    /*
+-     * Release the spin mutex acquired earlier and reenable interrupts on
+-     * this processor.
+-     */
+-    struct nvidia_softc *sc = nv->os_state;
+-    mtx_unlock_spin(&sc->mtx_rm);
+-#else
+     /*
+      * Restore the interrupt mask upon existing the critical code segment
+      * and thus allow interrupt handlers to execute again.
+      */
+-    struct nvidia_softc *sc = nv->os_state;
+-    splx(sc->spl);
+-#endif
 +    crit_exit();
- 
-     return 0;
  }
-@@ -297,7 +308,11 @@
-     u_long cmd,
-     caddr_t data,
-     int fflag,
-+#if !defined(__DragonFly__)
-     d_thread_t *td
-+#else 
-+    struct thread *td
-+#endif
- )
- {
-     struct nvidia_softc *sc;
-@@ -338,7 +353,11 @@
  
- int nvidia_close_ctl(
-     dev_t dev,
-+#if !defined(__DragonFly__)
-     d_thread_t *td
+ 
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_subr.c~ ./src/nvidia_subr.c~
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_subr.c~	1970-01-01 01:00:00.000000000 +0100
++++ ./src/nvidia_subr.c~	2004-08-04 21:32:49.000000000 +0200
+@@ -0,0 +1,1621 @@
++/* _NVRM_COPYRIGHT_BEGIN_
++ *
++ * Copyright 2001-2002 by NVIDIA Corporation.  All rights reserved.  All
++ * information contained herein is proprietary and confidential to NVIDIA
++ * Corporation.  Any use, reproduction, or disclosure without the written
++ * permission of NVIDIA Corporation is prohibited.
++ *
++ * _NVRM_COPYRIGHT_END_
++ */
++
++#include "nv-misc.h"
++#include "os-interface.h"
++#include "nv.h"
++#include "nv-dragonfly.h"
++
++
++devclass_t nvidia_devclass;
++nv_state_t nvidia_ctl_state;
++
++#define rman_get_extends(x) (rman_get_end(x) - rman_get_start(x) + 1)
++
++int nvidia_attach(device_t dev)
++{
++    int status;
++    struct nvidia_softc *sc;
++    nv_state_t *nv;
++
++    sc = device_get_softc(dev);
++    nv = sc->nv_state;
++
++    printf("nvidia_attach() called - state %d\n", nv);
++
++    nv->os_state         = sc;
++    nv->flags            = 0;
++    nv->device_number    = device_get_unit(dev);
++    nv->bus              = pci_get_bus(dev);
++    nv->slot             = pci_get_slot(dev);
++    nv->vendor_id        = pci_get_vendor(dev);
++    nv->device_id        = pci_get_device(dev);
++    nv->interrupt_line   = pci_get_irq(dev);
++    nv->bar.fb.address   = rman_get_start(sc->mem);
++    nv->bar.fb.size      = rman_get_extends(sc->mem);
++    nv->bar.fb.map       = NULL;
++    nv->bar.regs.address = rman_get_start(sc->reg);
++    nv->bar.regs.size    = rman_get_extends(sc->reg);
++    nv->bar.regs.map     = NULL;
++
++    if ((status = nvidia_dev_attach(sc)) != 0)
++        return status;
++
++    if ((status = nvidia_ctl_attach()) != 0)
++        return status;
++
++    nv_sysctl_init(nv);
++    return 0;
++}
++
++int nvidia_detach(device_t dev)
++{
++    int status;
++    struct nvidia_softc *sc;
++
++    sc = device_get_softc(dev);
++    nv_sysctl_exit(sc->nv_state);
++
++    status = nvidia_dev_detach(sc);
++    if (status) {
++        device_printf(dev, "NVRM: NVIDIA driver DEV detach failed.\n");
++        goto fail;
++    }
++
++    status = nvidia_ctl_detach();
++    if (status) {
++        device_printf(dev, "NVRM: NVIDIA driver CTL detach failed.\n");
++        goto fail;
++    }
++
++fail:
++    /* XXX Fix me? (state) */
++    return status;
++}
++
++
++#ifdef NV_SUPPORT_ACPI_PM
++int nvidia_suspend(device_t dev)
++{
++    struct nvidia_softc *sc;
++    nv_state_t *nv;
++    int status = RM_ERROR;
++
++    /* Only if ACPI is running */
++    if (devclass_get_softc(devclass_find("ACPI"), 0) == NULL)
++        return ENODEV;
++
++    sc = device_get_softc(dev);
++    nv = sc->nv_state;
++
++    NV_PCI_ENABLE_DEVICE(nv);
++
++    if (nv->pdev != NULL) {
++        /* Only if we have RM state */
++        status = rm_power_management(nv, 0, NV_PM_ACPI_STANDBY);
++    }
++
++    return status;
++}
++
++int nvidia_resume(device_t dev)
++{
++    struct nvidia_softc *sc;
++    nv_state_t *nv;
++    int status = RM_ERROR;
++
++    sc = device_get_softc(dev);
++    nv = sc->nv_state;
++
++    NV_PCI_ENABLE_DEVICE(nv);
++
++    if (nv->pdev != NULL) {
++        /* Only if we have RM state */
++        status = rm_power_management(nv, 0, NV_PM_ACPI_RESUME);
++    }
++
++    return status;
++}
++#endif /* NV_SUPPORT_ACPI_PM */
++
++
++int nvidia_alloc(device_t dev)
++{
++    int error = 0;
++    struct nvidia_softc *sc;
++
++    sc = device_get_softc(dev);
++    sc->dev = dev;
++
++    sc->nv_state = malloc(sizeof(nv_state_t), M_NVIDIA, M_WAITOK | M_ZERO);
++    if (sc->nv_state == NULL) {
++        error = ENOMEM;
++        goto fail;
++    }
++
++    sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->reg_rid,
++                    0, ~0, 1, 0);
++    if (sc->reg == NULL) {
++        device_printf(dev, "NVRM: NVIDIA REG resource alloc failed.\n");
++        error = ENXIO;
++        goto fail;
++    }
++
++    sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid,
++                    0, ~0, 1, 0);
++    if (sc->mem == NULL) {
++        device_printf(dev, "NVRM: NVIDIA MEM resource alloc failed.\n");
++        error = ENXIO;
++        goto fail;
++    }
++
++    sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
++                     0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
++    if (sc->irq == NULL) {
++        device_printf(dev, "NVRM: NVIDIA IRQ resource alloc failed.\n");
++        error = ENXIO;
++        goto fail;
++    }
++
++fail:
++    return (error);
++}
++
++void nvidia_free(device_t dev)
++{
++    struct nvidia_softc *sc;
++
++    sc = device_get_softc(dev);
++
++    if (sc->reg != NULL)
++        bus_release_resource(dev, SYS_RES_MEMORY, sc->reg_rid, sc->reg);
++    if (sc->mem != NULL)
++        bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
++    if (sc->irq != NULL)
++        bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
++    if (sc->iop != NULL)
++        bus_release_resource(dev, SYS_RES_IOPORT, sc->iop_rid, sc->iop);
++
++    if (sc->nv_state != NULL)
++        free(sc->nv_state, M_NVIDIA);
++}
++
++void nvidia_intr(void *xsc)
++{
++    struct nvidia_softc *sc;
++    nv_state_t *nv;
++    U032 run_bottom_half = 0;
++
++    sc = (struct nvidia_softc *) xsc;
++    nv = sc->nv_state;
++
++    NV_PCI_ENABLE_DEVICE(nv);
++    rm_isr(nv->device_number, &run_bottom_half);
++
++    if (run_bottom_half) {
++        /* We're not executing in an HW ISR context */
++        rm_isr_bh(nv->pdev);
++    }
++}
++
++int nvidia_post_vbios(struct nv_ioctl_post_vbios *pv)
++{
++    int i;
++    struct nvidia_softc *sc;
++    nv_state_t *nv;
++
++    for (i = 0; i < NV_MAX_DEVICES; i++) {
++        sc = devclass_get_softc(nvidia_devclass, i);
++        if (!sc)
++            continue;
++        nv = sc->nv_state;
++
++        if ((nv->bus == pv->bus) && (nv->slot == pv->slot) &&
++                (nv->flags & NV_FLAG_WAS_POSTED) == 0)
++            nv->flags |= NV_FLAG_NEEDS_POSTING;
++    }
++
++    return 0;
++}
++
++int nvidia_get_api_version(struct nv_ioctl_rm_api_version *av)
++{
++    av->major   = NV_MAJOR_VERSION;
++    av->minor   = NV_MINOR_VERSION;
++    av->patch   = NV_PATCHLEVEL;
++    av->version = NV_RM_API_VERSION;
++
++    return 0;
++}
++
++int nvidia_get_card_info(struct nv_ioctl_card_info *ci)
++{
++    int i;
++    struct nvidia_softc *sc;
++    nv_state_t *nv;
++
++    /*
++     * Clients supporting versioning will pass version magic in the first
++     * card information field.
++     */
++    struct nv_ioctl_rm_api_version *av = (void *) ci;
++
++    if (av->magic != NV_RM_API_VERSION_MAGIC_REQ ||
++        av->version != NV_RM_API_VERSION) {
++        /*
++         * This client either has no versioning support its version isn't
++         * identical to ours. While this is fine most of the time, it can
++         * result in severe problems.
++         */
++        av->magic   = NV_RM_API_VERSION_MAGIC_REP;
++        av->major   = NV_MAJOR_VERSION;
++        av->minor   = NV_MINOR_VERSION;
++        av->patch   = NV_PATCHLEVEL;
++        av->version = NV_RM_API_VERSION;
++
++        return -EINVAL;
++    }
++
++    /* clear card information structure */
++    memset(ci, 0, sizeof(ci));
++
++    for (i = 0; i < NV_MAX_DEVICES; i++) {
++        sc = devclass_get_softc(nvidia_devclass, i);
++        if (!sc)
++            continue;
++        nv = sc->nv_state;
++
++        ci[i].flags          = (NV_IOCTL_CARD_INFO_FLAG_PRESENT |
++                                NV_IOCTL_CARD_INFO_FLAG_NEED_MSYNC);
++        ci[i].bus            = nv->bus;
++        ci[i].slot           = nv->slot;
++        ci[i].vendor_id      = nv->vendor_id;
++        ci[i].device_id      = nv->device_id;
++        ci[i].interrupt_line = nv->interrupt_line;
++        ci[i].fb_address     = nv->bar.fb.address;
++        ci[i].fb_size        = nv->bar.fb.size;
++        ci[i].reg_address    = nv->bar.regs.address;
++        ci[i].reg_size       = nv->bar.regs.size;
++    }
++
++    return 0;
++}
++
++
++int nvidia_handle_ioctl(
++    dev_t dev,
++    u_long cmd,
++    caddr_t data,
++    int fflag,
++    d_thread_t *td
++)
++{
++    struct nvidia_softc *sc;
++    nv_state_t *nv;
++    int unit = minor(dev);
++
++    if (unit == CDEV_CTL_MINOR) {
++        /* the control device is "special" */
++        nv = &nvidia_ctl_state;
++    } else {
++        sc = devclass_get_softc(nvidia_devclass, unit);
++        if (!sc)
++            return ENXIO;
++        nv = sc->nv_state;
++    }
++
++    NV_PCI_ENABLE_DEVICE(nv);
++
++    if (rm_ioctl(nv, __TD_FDT(td), __NV_IOC_NR(cmd), data))
++        return 0;
++
++    return EINVAL;
++}
++
++
++int nvidia_open_ctl(void)
++{
++    struct nvidia_softc *sc;
++    nv_state_t *nv = &nvidia_ctl_state;
++
++    sc = nv->os_state;
++    sc->refcnt++;
++
++    nv->device_number = NV_CONTROL_DEVICE_NUMBER;
++
++    nv->flags |= NV_FLAG_OPEN;
++    nv->flags |= NV_FLAG_CONTROL;
++
++    nv->flags &= ~NV_FLAG_HOTKEY_OCCURRED;
++
++    return 0;
++}
++
++int nvidia_close_ctl(
++    dev_t dev,
++    d_thread_t *td
++)
++{
++    struct nvidia_softc *sc;
++    nv_state_t *nv = &nvidia_ctl_state;
++
++    if (__TD_FDT_CNT(td) == 0)
++        rm_free_unused_clients(nv, 0, __TD_FDT(td));
++
++    sc = nv->os_state;
++    sc->refcnt--;
++
++    if (sc->refcnt == 0) {
++        /*
++         * The control device has been released; without physical devices
++         * backing it, we only need to reset the flags.
++         */
++        nv->flags = 0;
++    }
++
++    return 0;
++}
++
++int nvidia_open_dev(struct nvidia_softc *sc)
++{
++    nv_state_t *nv = sc->nv_state;
++
++    NV_PCI_ENABLE_DEVICE(nv);
++
++    if ((nv->flags & NV_FLAG_OPEN) == 0) {
++        /*
++         * The device flags indicate that this device has not been opened
++         * or else shut down previously. There isn't much we can do here,
++         * the core resource manager does the actual work. We update both
++         * the flags and the usage count.
++         */
++        STAILQ_INIT(&sc->event_queue);
++
++        if (!rm_init_adapter(nv)) {
++            device_printf(sc->dev, "NVRM: rm_init_adapter() failed!\n");
++            return EIO;
++        }
++
++        nv->flags |= NV_FLAG_OPEN;
++    }
++
++    sc->refcnt++;
++
++    return 0;
++}
++
++int nvidia_close_dev(
++    struct nvidia_softc *sc,
++    dev_t dev,
++    d_thread_t *td
++)
++{
++    nv_state_t *nv = sc->nv_state;
++    nv_os_event_t *et;
++
++    NV_PCI_ENABLE_DEVICE(nv);
++
++    if (__TD_FDT_CNT(td) == 0)
++        rm_free_unused_clients(nv, 0, __TD_FDT(td));
++
++    sc->refcnt--;
++
++    if (sc->refcnt == 0) {
++        /*
++         * The usage count for this device has dropped to zero, it can be
++         * safely shut down. We don't need to wait for bottom-halfes like
++         * we do on Linux, they are not run asynchronously on FreeBSD. We
++         * do need to reset certain flags, though.
++         */
++        rm_disable_adapter(nv);
++        rm_shutdown_adapter(nv);
++
++        while ((et = STAILQ_FIRST(&sc->event_queue))) {
++            STAILQ_REMOVE(&sc->event_queue, et, nv_os_event, queue);
++            free(et, M_NVIDIA);
++        }
++
++        nv->flags &= ~NV_FLAG_OPEN;
++    }
++
++    return 0;
++}
++
++
++int nvidia_modevent(
++    module_t mod,
++    int what,
++    void *arg
++)
++{
++    nv_state_t *nv;
++    struct nvidia_softc *sc;
++
++    switch (what) {
++        case MOD_LOAD:
++            /*
++             * The module load event. Our KLD has just been loaded and is
++             * ready to initialize. We setup the core resource manager in
++             * this routine, further initialization takes place at attach
++             * time.
++             */
++            if (!rm_init_rm()) {
++                printf("NVRM: rm_init_rm() failed!\n");
++                return EIO;
++            }
++
++            nvidia_sysctl_init();
++            nvidia_linux_init();
++            rm_load_registry(nv_parms);
++
++            break;
++
++        case MOD_UNLOAD:
++            /*
++             * Check if the control device is still open and reject the
++             * unload request if it is. This event can occur even when the
++             * module usage count is non-zero!
++             */
++            nv = &nvidia_ctl_state;
++            sc = nv->os_state;
++
++            if (sc->refcnt != 0) /* XXX Fix me? (refcnt) */
++                return EBUSY;
++
++            rm_shutdown_rm();
++
++            nvidia_sysctl_exit();
++            nvidia_linux_exit();
++
++            break;
++
++        default:
++            break;
++    }
++
++    return 0;
++}
++
++
++#ifdef NV_SUPPORT_OS_AGP
++S032 nv_os_agp_init(
++    nv_state_t *nv,
++    void **base,
++    void **linear,
++    U032 *limit
++)
++{
++    void *bitmap;
++    struct nvidia_softc *sc = nv->os_state;
++    struct agp_info ai;
++
++    U032 mode = 0;
++    U032 fw   = 0;
++    U032 sba  = 0;
++    U032 rate = AGP_MODE_RATE_1x | AGP_MODE_RATE_2x | AGP_MODE_RATE_4x;
++    U032 size = 0;
++
++    sc->agp_dev = agp_find_device();
++    if (!sc->agp_dev) {
++        printf("NVRM: agp_find_device failed, chipset unsupported?\n");
++        return -ENODEV;
++    }
++
++    if (agp_acquire(sc->agp_dev) != 0)
++        return -EBUSY;
++
++    agp_get_info(sc->agp_dev, &ai);
++    mode = ai.ai_mode;
++
++    if (os_set_mem_range(ai.ai_aperture_base, ai.ai_aperture_size,
++                NV_MEMORY_WRITECOMBINED) != RM_OK) {
++        /*
++         * Failure to set a write-combining range for the AGP aperture is
++         * not necessarily a fatal error condition; we don't know at this
++         * point, however, and abort to prevent performance and stability
++         * problems that may be hard to track down otherwise.
++         */
++        agp_release(sc->agp_dev);
++        return -EIO;
++    }
++
++    rm_read_registry_dword(nv, "NVreg", "ReqAGPRate", &rate);
++    rm_read_registry_dword(nv, "NVreg", "EnableAGPFW", &fw);
++    rm_read_registry_dword(nv, "NVreg", "EnableAGPSBA", &sba);
++
++    mode = AGP_MODE_SET_RATE(mode, AGP_MODE_GET_RATE(mode) & rate);
++    mode = AGP_MODE_SET_FW(mode, fw);
++    mode = AGP_MODE_SET_SBA(mode, sba);
++
++    if (agp_enable(sc->agp_dev, mode) != 0) {
++        agp_release(sc->agp_dev);
++        os_unset_mem_range(ai.ai_aperture_base, ai.ai_aperture_size);
++        return -EIO;
++    }
++
++    size = ai.ai_aperture_size / RM_PAGE_SIZE / 8;
++    
++    if (os_alloc_mem(&bitmap, size) != RM_OK) {
++        agp_release(sc->agp_dev);
++        os_unset_mem_range(ai.ai_aperture_base, ai.ai_aperture_size);
++        return -EIO;
++    }
++
++    os_mem_set(bitmap, 0xff, size);
++
++    if (rm_set_agp_bitmap(nv, bitmap) != RM_OK) {
++        agp_release(sc->agp_dev);
++        os_free_mem(bitmap);
++        os_unset_mem_range(ai.ai_aperture_base, ai.ai_aperture_size);
++        return -EIO;
++    }
++
++    *base   = (void *) ai.ai_aperture_base;
++    *linear = (void *) ai.ai_aperture_va;
++    *limit  = (U032)   ai.ai_aperture_size - 1;
++
++    return 0;
++}
++
++S032 nv_os_agp_teardown(nv_state_t *nv)
++{
++    struct nvidia_softc *sc = nv->os_state;
++    void *bitmap;
++
++    if (agp_release(sc->agp_dev) != 0)
++        return -EBUSY;
++
++    rm_clear_agp_bitmap(nv, &bitmap);
++    os_free_mem(bitmap);
++
++    os_unset_mem_range(nv->agp.address, nv->agp.size);
++
++    return 0;
++}
++#endif /* NV_SUPPORT_OS_AGP */
++
++S032 nv_agp_init(
++    nv_state_t *nv,
++    void **base,
++    void **linear,
++    void *limit,
++    U032 config
++)
++{
++    if (config == NVOS_AGP_CONFIG_DISABLE_AGP)
++        return 1;
++
++    if ((config & NVOS_AGP_CONFIG_OSAGP) != 0) {
++#ifndef NV_SUPPORT_OS_AGP
++        /*
++         * Inform the user that the kernel module needs to be built
++         * with FreeBSD AGP GART driver (agp.ko) support.
++         */
++        /* XXX Fix me? (agp.ko) */
++        /* printf("NVRM: build nvidia.ko with FreeBSD agp.ko support.\n"); */
 +#else
-+    struct thread *td
-+#endif
- )
- {
-     nv_state_t *nv = &nvidia_ctl_state;
-@@ -762,7 +781,12 @@
-      * of our system calls at a time.
-      */
-     struct nvidia_softc *sc = nv->os_state;
-+#ifndef __DragonFly__
-     lockmgr(&sc->api_lock, LK_EXCLUSIVE, 0, curproc);
++        if (nv_os_agp_init(nv, base, linear, limit) == 0) {
++            /*
++             * If the operating system AGP GART driver successfully
++             * configured its backend, apply chipset overrides.
++             */
++            rm_update_agp_config(nv);
++            nv->agp_config = NVOS_AGP_CONFIG_OSAGP;
++            return 0;
++        }
++#endif /* NV_SUPPORT_OS_AGP */
++    }
++
++    if ((config & NVOS_AGP_CONFIG_NVAGP) == 0)
++        goto failed;
++
++    if (devclass_get_softc(devclass_find("agp"), 0) != NULL) {
++        /*
++         * Make sure we don't try to use the internal GART driver when
++         * the OS AGPGART driver (agp.ko) is attached. While that may
++         * be perfectly fine on most systems, but is known to break on
++         * some.
++         * -------------------------------------------------------------
++         * DON'T REDISTRIBUTE THE DRIVER WITH THIS SANITY CHECK REMOVED!
++         * -------------------------------------------------------------
++         */
++        printf("NVRM: detected agp.ko, aborting NVIDIA AGP setup!\n");
++        goto failed;
++    }
++
++    if (rm_init_agp(nv) == RM_OK) {
++        nv->agp_config = NVOS_AGP_CONFIG_NVAGP;
++        return 0;
++    }
++
++failed:
++    nv->agp_config = NVOS_AGP_CONFIG_DISABLE_AGP;
++    return -EIO;
++}
++
++S032 nv_agp_teardown(nv_state_t *nv)
++{
++    S032 status = -EINVAL;
++
++    switch (nv->agp_config) {   /* see above */
++#ifdef NV_SUPPORT_OS_AGP
++        case NVOS_AGP_CONFIG_OSAGP:
++            /*
++             * Release the backend, the AGP core logic will remain
++             * initialized. This is by design (agp.ko).
++             */
++            status = nv_os_agp_teardown(nv);
++            break;
++#endif
++        case NVOS_AGP_CONFIG_NVAGP:
++            /*
++             * Shut down the NVIDIA AGP GART driver, clearning all
++             * internal state.
++             */
++            status = rm_teardown_agp(nv);
++            break;
++    }
++
++    nv->agp_config = NVOS_AGP_CONFIG_DISABLE_AGP;
++    return status;
++}
++
++S032 nv_no_incoherent_mappings(void)
++{
++    /* XXX Fix me! (no_incoherent_mappings) */
++    return 0;
++}
++
++void* nv_find_agp_kernel_mapping(
++    nv_state_t *nv,
++    ULONG address
++)
++{
++    /* XXX Implement me? (kmap lookup) */
++    return NULL;
++}
++
++
++void nv_lock_rm(nv_state_t *nv)
++{
++    /* 
++     * While SMP configurations are handled with a global kernel lock and
++     * in such a way that only one of the CPUs is executing a process and
++     * servicing interrupts at any point in time, it is possible that the
++     * interrupt handlers (th/bh) may interfere with critical code.
++     *
++     * This "lock" thus disables interrupts for the duration of this code
++     * segment's execution.
++     */
++    crit_enter();
++}
++
++void nv_unlock_rm(nv_state_t *nv)
++{
++    /*
++     * Restore the interrupt mask upon existing the critical code segment
++     * and thus allow interrupt handlers to execute again.
++     */
++    crit_exit();
++}
++
++
++void nv_lock_api(nv_state_t *nv)
++{
++    /*
++     * Since it is entirely possible that we involuntarily go to sleep at
++     * certain points in time, we make sure that we execute only a single
++     * of our system calls at a time.
++     */
++    struct nvidia_softc *sc = nv->os_state;
++    lockmgr(&sc->api_lock, LK_EXCLUSIVE, 0, CURTHREAD);
++}
++
++void nv_unlock_api(nv_state_t *nv)
++{
++    /*
++     * Release the API lock and allow a process sleeping on it to execute
++     * its system call.
++     */
++    struct nvidia_softc *sc = nv->os_state;
++    lockmgr(&sc->api_lock, LK_RELEASE, 0, CURTHREAD);
++}
++
++
++void nv_post_event(
++    nv_state_t *nv,
++    nv_event_t *event,
++    U032 hObject,
++    U032 index
++)
++{
++    struct nvidia_softc *sc;
++    nv_os_event_t *et; 
++
++    if (!(et = malloc(sizeof(nv_os_event_t), M_NVIDIA, M_ZERO)))
++        return;
++
++    et->event = *event;
++    et->event.hObject = hObject;
++    et->event.index = index;
++
++    nv_lock_rm(nv);
++
++    sc = nv->os_state;
++    STAILQ_INSERT_TAIL(&sc->event_queue, et, queue);
++
++    nv_unlock_rm(nv);
++
++/*  printf("NVRM: nv_post_event()\n");
++    printf("NVRM:     hParent: 0x%08x\n", et->event.hParent);
++    printf("NVRM:     hObject: 0x%08x\n", et->event.hObject); */
++
++    /* XXX Fix me? (os events) */
++    selwakeup(&sc->rsel);
++}
++
++S032 nv_get_event(
++    nv_state_t *nv,
++    void *file,
++    nv_event_t *event,
++    U032 *pending
++)
++{
++    struct nvidia_softc *sc = nv->os_state;
++    nv_os_event_t *et;
++
++    nv_lock_rm(nv);
++
++    if (!(et = STAILQ_FIRST(&sc->event_queue))) {
++        nv_unlock_rm(nv);
++        return RM_ERROR; /* RM polling? */
++    }
++
++    *event = et->event;
++
++    STAILQ_REMOVE_HEAD(&sc->event_queue, queue);
++    free(et, M_NVIDIA);
++
++/*  printf("NVRM: nv_get_event(), %d\n", *pending);
++    printf("NVRM:     hParent: 0x%08x\n", event->hParent);
++    printf("NVRM:     hObject: 0x%08x\n", event->hObject); */
++    
++    /* XXX: Fix me? (os events) */
++    *pending = !(STAILQ_EMPTY(&sc->event_queue));
++
++    nv_unlock_rm(nv);
++
++    return RM_OK;
++}
++
++void* nv_find_alloc(
++    nv_state_t *nv,
++    vm_offset_t address
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++
++    SLIST_FOREACH(at, &sc->alloc_list, list) {
++        /*
++         * XXX Match an incoming address to a known allocation. We
++         * should use type flags here.
++         */
++        if (at->address == address)
++            return (void *) at;
++    }
++
++    return NULL;
++}
++
++void* nv_find_alloc_obj(
++    nv_state_t *nv,
++    vm_offset_t object
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++
++    SLIST_FOREACH(at, &sc->alloc_list, list) {
++        /*
++         * XXX Match the incoming object to a known allocation. We
++         * should use type flags here.
++         */
++        if (at->object == (vm_object_t) object)
++            return (void *) at;
++    }
++
++    return NULL;
++}
++
++void* nv_find_nv_mapping(
++    nv_state_t *nv,
++    ULONG address
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++    vm_offset_t offset, linear;
++
++    offset = (vm_offset_t) address & PAGE_MASK;
++    address &= ~PAGE_MASK;
++
++    SLIST_FOREACH(at, &sc->alloc_list, list) {
++        /*
++         * XXX Match an incoming address to a known allocation. We
++         * should use type flags here.
++         */
++        if (at->address == 0)
++            continue;
++        linear = at->address;
++        do {
++            if (vtophys(linear) == (vm_offset_t) address)
++                return (void *)(linear + offset);
++            linear += PAGE_SIZE;
++        } while (linear < (at->address + at->size));
++    }
++
++    return NULL;
++}
++
++ULONG nv_find_dma_mapping(
++    nv_state_t *nv,
++    ULONG address
++)
++{
++    /* XXX Fix me? (x86 only, amd64 dma) */
++    return address;
++}
++
++S032 nv_agp_translate_address(
++    nv_state_t *nv,
++    void *base,
++    U032 index,
++    U032 *address
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++
++    vm_page_t m;
++
++    SLIST_FOREACH(at, &sc->alloc_list, list) {
++        /*
++         * The purpose of this function is to extract the actual physical
++         * addresses of each page in the allocation with the base address
++         * passed by the caller.
++         */
++        if (at->object == (vm_object_t) base &&
++            at->size > index * PAGE_SIZE) {
++            VM_OBJECT_LOCK(at->object);
++            m = vm_page_lookup(at->object, index);
++            *address = VM_PAGE_TO_PHYS(m);
++            VM_OBJECT_UNLOCK(at->object);
++            return 0;
++        }
++    }
++
++    return -1;
++}
++
++S032 nv_alloc_contig_pages(
++    nv_state_t *nv,
++    void **address,
++    U032 count
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++    U032 size = count * PAGE_SIZE;
++
++    if (os_alloc_contig_pages(address, size) != RM_OK)
++        return -ENOMEM;
++
++    at = malloc(sizeof(nv_alloc_t), M_NVIDIA, M_WAITOK | M_ZERO);
++    if (!at) {
++        os_free_contig_pages(*address, size);
++        return -ENOMEM;
++    }
++
++    at->object = 0;
++    at->size = size;
++    at->address = (vm_offset_t) *address;
++    at->offset = ~0;
++
++    SLIST_INSERT_HEAD(&sc->alloc_list, at, list);
++
++    return 0;
++}
++
++S032 nv_free_contig_pages(
++    nv_state_t *nv,
++    void *address
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++    U032 size;
++
++    at = nv_find_alloc(nv, (vm_offset_t) address);
++    if (!at) {
++        os_dbg_breakpoint();
++        return -EINVAL;
++    }
++
++    size = at->size;
++    SLIST_REMOVE(&sc->alloc_list, at, nv_alloc, list);
++
++    free(at, M_NVIDIA);
++    os_free_contig_pages(address, size);
++
++    return 0;
++}
++
++S032 nv_alloc_system_pages(
++    nv_state_t  *nv,
++    void **address,
++    U032 count
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++
++    void *vm;
++    u_int32_t i, size = count * PAGE_SIZE;
++
++    at = malloc(sizeof(nv_alloc_t), M_NVIDIA, M_WAITOK | M_ZERO);
++    if (!at) {
++        return -ENOMEM;
++    }
++
++    vm = malloc(size, M_NVIDIA, M_WAITOK | M_ZERO);
++    if (!vm) {
++        free(at, M_NVIDIA);
++        return -ENOMEM;
++    }
++
++    at->pte = malloc(sizeof(vm_offset_t) * count, M_NVIDIA, M_WAITOK);
++    if (!at->pte) {
++        free(at, M_NVIDIA);
++        free(vm, M_NVIDIA);
++        return -ENOMEM;
++    }
++
++    for (i = 0; i < count; i++) {
++        at->pte[i] = vtophys((vm_offset_t) vm + (i * PAGE_SIZE));
++        vm_page_lock_queues();
++        vm_page_wire(PHYS_TO_VM_PAGE(at->pte[i]));
++        vm_page_unlock_queues();
++    }
++
++    at->object = 0;
++    at->size = size;
++    at->address = (vm_offset_t) vm;
++    at->offset = ~0;
++
++    SLIST_INSERT_HEAD(&sc->alloc_list, at, list);
++    *address = (void *) at->address;
++
++    return 0;
++}
++
++S032 nv_free_system_pages(
++    nv_state_t *nv,
++    void *address
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++
++    vm_offset_t pa;
++    u_int32_t i, count;
++
++    at = nv_find_alloc(nv, (vm_offset_t) address);
++    if (!at) {
++        os_dbg_breakpoint();
++        return -EINVAL;
++    }
++
++    count = at->size / PAGE_SIZE;
++    SLIST_REMOVE(&sc->alloc_list, at, nv_alloc, list);
++
++    for (i = 0; i < count; i++) {
++        pa = vtophys(at->address + (i * PAGE_SIZE));
++        vm_page_lock_queues();
++        vm_page_unwire(PHYS_TO_VM_PAGE(pa), 0);
++        vm_page_unlock_queues();
++    }
++
++    free(at->pte, M_NVIDIA);
++    free(at, M_NVIDIA);
++    free(address, M_NVIDIA);
++
++    return 0;
++}
++
++
++S032 nv_alloc_vm_object(
++    nv_state_t *nv,
++    void **address,
++    U032 count
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++
++    u_int32_t i, j;
++    vm_page_t m;
++    vm_object_t object;
++
++    at = malloc(sizeof(nv_alloc_t), M_NVIDIA, M_WAITOK | M_ZERO);
++    if (!at) {
++        return -ENOMEM;
++    }
++
++    object = vm_object_allocate(OBJT_DEFAULT, count);
++
++    for (i = 0; i < count; i++) {
++        /*
++         * Find the individual pages belonging to the allocation from the
++         * VM object; since this is the first time they're accessed, they
++         * will be allocated.
++         */
++
++#if __FreeBSD_version >= 500000
++        /*
++         * Request that this range of pages be wired down to prevent them
++         * from being paged out. This is done below for FreeBSD 4.
++         */
++        VM_OBJECT_LOCK(object);
++        m = vm_page_grab(object, i, VM_ALLOC_NORMAL | VM_ALLOC_WIRED);
++        VM_OBJECT_UNLOCK(object);
 +#else
-+    lockmgr(&sc->api_lock, LK_EXCLUSIVE, NULL, curthread);
++        m = vm_page_grab(object, i, VM_ALLOC_NORMAL);
 +#endif
++        if (!m) {
++            VM_OBJECT_LOCK(object);
++            for (j = 0; j < i; j++) {
++                m = vm_page_lookup(object, j);
++                vm_page_lock_queues();
++                vm_page_unwire(m, 0);
++                vm_page_unlock_queues();
++            }
++            VM_OBJECT_UNLOCK(object);
++            return -ENOMEM;
++        }
++
++#if __FreeBSD_version < 500000
++        vm_page_wire(m);
++#endif
++        vm_page_lock_queues();
++        vm_page_wakeup(m);
++        vm_page_unlock_queues();
++    }
++
++    at->object = object;
++    at->offset = ~0;
++    at->size = ptoa(count);
++    at->address = 0;
++
++    SLIST_INSERT_HEAD(&sc->alloc_list, at, list);
++    *address = (void *) at->object;
++
++    return 0;
++}
++
++S032 nv_free_vm_object(
++    nv_state_t *nv,
++    void *address
++)
++{
++    nv_alloc_t *at;
++    struct nvidia_softc *sc = nv->os_state;
++
++    vm_page_t m;
++    u_int32_t i, count;
++
++    at = nv_find_alloc_obj(nv, (vm_offset_t) address);
++    if (!at) {
++        os_dbg_breakpoint();
++        return -EINVAL;
++    }
++
++    count = at->size / PAGE_SIZE;
++    SLIST_REMOVE(&sc->alloc_list, at, nv_alloc, list);
++
++    VM_OBJECT_LOCK(at->object);
++    for (i = 0; i < count; i++) {
++        /*
++         * Release "one wiring" of this page; this may reenable paging as
++         * a result, depending on the total number of "wirings".
++         */
++        m = vm_page_lookup(at->object, i);
++        vm_page_lock_queues();
++        vm_page_unwire(m, 0);
++        vm_page_unlock_queues();
++    }
++    VM_OBJECT_UNLOCK(at->object);
++
++    vm_object_deallocate(at->object);
++    free(at, M_NVIDIA);
++
++    return 0;
++}
++
++
++#ifdef NV_SUPPORT_OS_AGP
++S032 nv_alloc_agp_pages(
++    nv_state_t *nv,
++    void **address,
++    U032 count,
++    U032 offset,
++    void **private
++)
++{
++    void *handle;
++    struct nvidia_softc *sc = nv->os_state;
++
++    handle = agp_alloc_memory(sc->agp_dev, 0, count << PAGE_SHIFT);
++    if (!handle) {
++        /*
++         * This is very unlikely to happen, the system's memory resources
++         * would have to be nearly exhausted.
++         */
++        return -ENOMEM;
++    }
++
++    if (agp_bind_memory(sc->agp_dev, handle, offset) != 0) {
++        /*
++         * This shouldn't happen, we claimed the AGP backend and are thus
++         * using it exclusively; the resource manager manages AGP offsets
++         * internally, we wouldn't have been called had we run out of AGP
++         * aperture space.
++         */
++        os_dbg_breakpoint();
++
++        agp_free_memory(sc->agp_dev, handle);
++        return -ENOMEM;
++    }
++
++    *private = handle;
++    return 0;
++}
++
++S032 nv_free_agp_pages(
++    nv_state_t *nv,
++    void **address,
++    U032 count,
++    void *handle
++)
++{
++    struct nvidia_softc *sc = nv->os_state;
++
++    if (agp_unbind_memory(sc->agp_dev, handle) != 0) {
++        /*
++         * This is the only place where previously bound AGP memory would
++         * be freed. If we fail to unbind this memory now, something very
++         * wrong must have happened.
++         */
++        os_dbg_breakpoint();
++    }
++
++    agp_free_memory(sc->agp_dev, handle);
++    return 0;
++}
++#endif /* NV_SUPPORT_OS_AGP */
++
++
++S032 nv_alloc_pages(
++    nv_state_t *nv,
++    void **address,
++    U032 count,
++    U032 alloc_type_agp,
++    U032 alloc_type_contiguous,
++    U032 cache,
++    U032 alloc_type_kernel,
++    U032 class,
++    void **private
++)
++{
++    /* XXX Fix me! (cache types) */
++    U032 alloc_type_cached = (cache != NV_MEMORY_UNCACHED);
++
++    if (alloc_type_agp) {
++#ifdef NV_SUPPORT_OS_AGP
++        U032 offset;
++
++        if ((nv->agp_config & NVOS_AGP_CONFIG_OSAGP) == 0)
++            return -EINVAL;
++
++        if (rm_alloc_agp_bitmap(nv, count, &offset) != RM_OK) {
++            /*
++             * We've run out of AGP aperture space, the requestor will be
++             * forced to fall back to general system memory.
++             */
++            return -ENOMEM;
++        }
++
++        if (nv_alloc_agp_pages(nv, address, count, offset << PAGE_SHIFT,
++                private) != 0) {
++            /*
++             * The AGP aperture is managed internally by core resman, the
++             * offset passed to us should work; thus, this shouldn't fail
++             * unless the system memory is exhausted.
++             */
++            rm_free_agp_bitmap(nv, offset, count);
++            return -ENOMEM;
++        }
 +
- #endif
- }
- 
-@@ -781,7 +805,12 @@
-      * its system call.
-      */
-     struct nvidia_softc *sc = nv->os_state;
-+#ifndef __DragonFly__
-     lockmgr(&sc->api_lock, LK_RELEASE, 0, curproc);
++        *address = (void *)(nv->agp.address + (offset << PAGE_SHIFT));
++        return 0;
 +#else
-+    lockmgr(&sc->api_lock, LK_RELEASE, NULL, curthread);
-+#endif
++        nv_alloc_t *at;
 +
- #endif
- }
- 
-@@ -1677,7 +1706,8 @@
-      * timeout.
-      */
-     sc = nv->os_state;
--    sc->timer_ch = timeout(nvidia_rc_timer, (void *) nv, hz);
++        if ((nv->agp_config & NVOS_AGP_CONFIG_NVAGP) == 0)
++            return -EINVAL;
 +
-+    callout_reset(&sc->timer_ch, hz, nvidia_rc_timer, nv);
- }
- 
- int nv_start_rc_timer(
-@@ -1689,7 +1719,8 @@
-     if (nv->rc_timer_enabled != 0)
-         return -EIO;
- 
--    sc->timer_ch = timeout(nvidia_rc_timer, (void *) nv, hz);
-+    callout_reset(&sc->timer_ch, hz, nvidia_rc_timer, nv);
++        if (nv_alloc_vm_object(nv, address, count) != 0) {
++            /*
++             * Hopefully, this error condition will be much more unlikely
++             * to occur than failure to allocate the same number of pages
++             * with nv_alloc_system_pages.
++             */
++            return -ENOMEM;
++        }
++
++        at = nv_find_alloc_obj(nv, (vm_offset_t) *address);
++        if (!at) {
++            os_dbg_breakpoint();
++            return -ENOMEM;
++        }
++
++        if (rm_alloc_agp_pages(nv, address, count, class, private,
++                &at->offset) != RM_OK) {
++            /*
++             * In theory, this should only fail if we run out of aperture
++             * space (which is not unlikely).
++             */
++            nv_free_vm_object(nv, *address);
++            return -ENOMEM;
++        }
++
++        *address = (void *)(nv->agp.address + (at->offset << PAGE_SHIFT));
++        return 0;
++#endif /* NV_SUPPORT_OS_AGP */
++    } else {
++        /*
++         * Save the allocation parameters for use in nv_free_pages, where
++         * we won't have access to all of them (sigh).
++         */
++        nv_alloc_private_t *ap;
++        vm_offset_t vm;
++
++        /* XXX Fix me! (PAT) */
++        if (cache == NV_MEMORY_WRITECOMBINED)
++            return -ENOMEM;
++
++        ap = malloc(sizeof(nv_alloc_private_t), M_NVIDIA, M_WAITOK | M_ZERO);
++        if (!ap) {
++            return -ENOMEM;
++        }
++        *private = (void *) ap;
++
++        ap->count = count;
++        ap->alloc_type_contiguous = alloc_type_contiguous;
++        ap->alloc_type_cached = alloc_type_cached;
++        ap->alloc_type_kernel = alloc_type_kernel;
++        ap->class = class;
++
++        if (alloc_type_kernel &&
++            !alloc_type_contiguous && alloc_type_cached) {
++            /*
++             * Obtain general system memory for the resource mananger, it
++             * doesn't need to be contiguous.
++             */
++            if (nv_alloc_system_pages(nv, address, count))
++                goto failed;
++
++        } else if (alloc_type_contiguous ||
++                   (alloc_type_kernel && !alloc_type_cached)) {
++            /*
++             * Make sure the pages are contiguous in physical memory; the
++             * memory will not be used for DMA push buffers, the returned
++             * linear mapping is expected to be usable as-is.
++             */
++            if (nv_alloc_contig_pages(nv, address, count))
++                goto failed;
++
++            /* XXX Fix me! (uc kernel) */
++            if (alloc_type_kernel && !alloc_type_cached)
++                /* goto failed */;
++
++        } else if (!alloc_type_kernel) {
++            /*
++             * Allocate general system memory for DMA push buffers. These
++             * pages may be non-contiguous; the individual addresses must
++             * be retrievable from the mmap(2) implementation.
++             */
++            if (nv_alloc_system_pages(nv, address, count))
++                goto failed;
++
++            vm = ((vm_offset_t) *address) - VM_MIN_KERNEL_ADDRESS;
++            *address = (void *) vm;
++        }
++
++        return 0;
++
++failed:
++        free(*private, M_NVIDIA);
++        return -ENOMEM;
++    }
++}
++
++S032 nv_free_pages(
++    nv_state_t *nv,
++    void **address,
++    U032 count,
++    U032 alloc_type_agp,
++    void *private
++)
++{
++    U032 offset;
++    offset = ((U032) *address - nv->agp.address) >> PAGE_SHIFT;
++
++    if (alloc_type_agp) {
++#ifdef NV_SUPPORT_OS_AGP
++        if ((nv->agp_config & NVOS_AGP_CONFIG_OSAGP) == 0)
++            return -EINVAL;
++
++        if (nv_free_agp_pages(nv, address, count, private) != 0) {
++            /*
++             * The following is a sanity check, this mustn't ever fail in
++             * in real-world scenario.
++             */
++            os_dbg_breakpoint();
++            return -EINVAL;
++        }
 +
-     nv->rc_timer_enabled = 1;
- 
-     return 0;
-@@ -1704,7 +1735,8 @@
-     if (nv->rc_timer_enabled == 0)
-         return -EIO;
- 
--    untimeout(nvidia_rc_timer, (void *) nv, sc->timer_ch);
-+    callout_stop(&sc->timer_ch);
++        rm_free_agp_bitmap(nv, offset, count);
++#else
++        nv_alloc_t *at;
++        struct nvidia_softc *sc = nv->os_state;
 +
-     nv->rc_timer_enabled = 0;
- 
-     return 0;
-diff -urN ./src/nvidia_sysctl.c ../../nvidia-patched/src/nvidia_sysctl.c
---- ./src/nvidia_sysctl.c	2003-05-28 18:51:52.000000000 +0200
-+++ ../../nvidia-patched/src/nvidia_sysctl.c	2004-07-21 10:14:32.000000000 +0200
-@@ -11,7 +11,11 @@
++        if ((nv->agp_config & NVOS_AGP_CONFIG_NVAGP) == 0)
++            return -EINVAL;
++
++        if (rm_free_agp_pages(nv, address, private) != RM_OK) {
++            /*
++             * Don't free the underlying system memory unless the request
++             * to free the RM AGP resources completes successfully, which
++             * should never actually fail.
++             */
++            os_dbg_breakpoint();
++            return -EINVAL;
++        }
++
++        SLIST_FOREACH(at, &sc->alloc_list, list) {
++            if (at->offset == offset) {
++                nv_free_vm_object(nv, (void *)at->object);
++                break;
++            }
++        }
++#endif /* NV_SUPPORT_OS_AGP */
++
++        return 0;
++    } else {
++        nv_alloc_private_t *ap;
++        vm_offset_t vm;
++
++	ap = (nv_alloc_private_t *) private;
++        if (!ap) {
++            os_dbg_breakpoint();
++            return -EINVAL;
++        }
++
++        if (ap->alloc_type_kernel &&
++            !ap->alloc_type_contiguous && ap->alloc_type_cached) {
++            /*
++             * Generic system memory used by the resource manager; almost
++             * identical to the user memory case.
++             */
++            if (nv_free_system_pages(nv, *address))
++                return -EINVAL;
++
++        } else if (ap->alloc_type_contiguous ||
++                   (ap->alloc_type_kernel && !ap->alloc_type_cached)) {
++            /*
++             * Free contigous system memory; this resource is rarely used
++             * and hence managed globally.
++             */
++            if (nv_free_contig_pages(nv, *address))
++                return -EINVAL;
++
++            /* XXX Fix me! (uc kernel) */
++            if (ap->alloc_type_kernel && !ap->alloc_type_cached)
++                /* return -EINVAL */;
++
++        } else if (!ap->alloc_type_kernel) {
++            /*
++             * XXX Generic system memory used for DMA push buffers. There
++             * are munmap(2) considerations in this case on Linux, are we
++             * really safe here?
++             */
++            vm = (vm_offset_t) *address;
++            *address = (void *)(vm + VM_MIN_KERNEL_ADDRESS);
++
++            if (nv_free_system_pages(nv, *address))
++                return -EINVAL;
++        }
++
++        free(ap, M_NVIDIA);
++        return 0;
++    }
++
++    return -EINVAL;
++}
++
++ULONG nv_get_kern_phys_address(ULONG address)
++{
++    vm_offset_t va = (vm_offset_t) address;
++
++    if (va < VM_MIN_KERNEL_ADDRESS) {
++        os_dbg_breakpoint();
++        return 0;
++    }
++
++    return vtophys(va);
++}
++
++ULONG nv_get_user_phys_address(ULONG address)
++{
++    struct vmspace *vm;
++    vm_offset_t va = (vm_offset_t) address;
++
++    if (va >= VM_MIN_KERNEL_ADDRESS) {
++        os_dbg_breakpoint();
++        return 0;
++    }
++
++    if (vm_fault_quick((caddr_t) va, VM_PROT_WRITE))
++        return 0;
++
++    vm = curproc->p_vmspace;
++    return pmap_extract(vmspace_pmap(vm), va);
++}
++
++
++int nvidia_mmap_dev(
++    struct nvidia_softc *sc,
++    vm_offset_t offset,
++    vm_offset_t *physical
++)
++{
++    nv_alloc_t *at;
++    nv_state_t *nv = sc->nv_state;
++
++    NV_PCI_ENABLE_DEVICE(nv);
++
++    /*
++     * Offsets that fall into the frame buffer, registry or AGP apertures
++     * are physical addresses and mapped into user-space directly. We can
++     * only do some basic sanity checking here.
++     */
++    if (IS_FB_OFFSET(nv, offset, PAGE_SIZE)) {
++        *physical = offset;
++        return 0;
++    }
++    
++    if (IS_REG_OFFSET(nv, offset, PAGE_SIZE)) {
++        *physical = offset;
++        return 0;
++    }
++    
++    if (IS_AGP_OFFSET(nv, offset, PAGE_SIZE)) {
++        *physical = offset;
++        return 0;
++    }
++
++    offset += VM_MIN_KERNEL_ADDRESS;
++
++    /*
++     * If the offset does not fall into any of the relevant apertures, we
++     * must assume that it corresponds to a memory allocation. Offsets of
++     * this kind are kernel virtual addresses that fall within one of the
++     * allocated ranges, provided they are valid. These logical addresses
++     * are translated into physical addresses and then mapped.
++     */
++    SLIST_FOREACH(at, &sc->alloc_list, list) {
++        if (offset >= at->address &&
++                offset < at->address + at->size) {
++            *physical = vtophys(offset);
++            return 0;
++        }
++    }
++
++    return -1;
++}
++
++
++int nv_int10h_call(
++    nv_state_t * nv,
++    U032 *eax,
++    U032 *ebx,
++    U032 *ecx,
++    U032 *edx,
++    void *buffer
++)
++{
++#ifdef NV_USE_OS_VM86_INT10CALL
++    struct vm86frame vmf;
++
++    vmf.vmf_eax = *eax;
++    vmf.vmf_ebx = *ebx;
++    vmf.vmf_ecx = *ecx;
++    vmf.vmf_edx = *edx;
++
++    if (vm86_intcall(0x10, &vmf) == 0) {
++        *eax = vmf.vmf_eax;
++        *ebx = vmf.vmf_ebx;
++        *ecx = vmf.vmf_ecx;
++        *edx = vmf.vmf_edx;
++        return RM_OK;
++    }
++#endif /* NV_USE_OS_VM86_INT10CALL */
++
++    return RM_ERROR;  /* XXX Fixm me? (vm86_intcall) */
++}
++
++void nvidia_rc_timer(void *data)
++{
++    nv_state_t *nv = (nv_state_t *) data;
++    struct nvidia_softc *sc;
++    
++    NV_PCI_ENABLE_DEVICE(nv);
++
++    /*
++     * We need this timer to trigger again one second from
++     * now, reset the timeout.
++     */
++    rm_run_rc_callback(nv);
++
++    sc = nv->os_state;
++    sc->timer_ch = timeout(nvidia_rc_timer, (void *) nv, hz);
++}
++
++int nv_start_rc_timer(
++    nv_state_t *nv
++)
++{
++    struct nvidia_softc *sc = nv->os_state;
++
++    if (nv->rc_timer_enabled != 0)
++        return -EIO;
++
++    sc->timer_ch = timeout(nvidia_rc_timer, (void *) nv, hz);
++    nv->rc_timer_enabled = 1;
++
++    return 0;
++}
++
++int nv_stop_rc_timer(
++    nv_state_t *nv
++)
++{
++    struct nvidia_softc *sc = nv->os_state;
++
++    if (nv->rc_timer_enabled == 0)
++        return -EIO;
++
++    untimeout(nvidia_rc_timer, (void *) nv, sc->timer_ch);
++    nv->rc_timer_enabled = 0;
++
++    return 0;
++}
++
+diff -urN ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_sysctl.c ./src/nvidia_sysctl.c
+--- ../../NVIDIA-FreeBSD-x86-1.0-6113/src/nvidia_sysctl.c	2004-08-03 01:27:38.000000000 +0200
++++ ./src/nvidia_sysctl.c	2004-08-04 21:26:57.000000000 +0200
+@@ -11,7 +11,7 @@
  #include "nv-misc.h"
  #include "os-interface.h"
  #include "nv.h"
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
- #include "nv-freebsd.h"
-+#else
+-#include "nv-freebsd.h"
 +#include "nv-dragonfly.h"
-+#endif
  
  struct sysctl_ctx_list sysctl_ctx;
  
-@@ -231,7 +235,11 @@
-                  * It also doesn't make sense to to iterate over multiple
-                  * functions if this isn't a multi-function device.
-                  */
-+#if defined(__FreeBSD__) && !defined(__DragonFly__)
-                 hdrtype = pci_read_config(dev, PCIR_HEADERTYPE, 1);
-+#else
-+                hdrtype = pci_read_config(dev, PCIR_HDRTYPE, 1);
-+#endif
- 
-                 if ((hdrtype & PCIM_MFDEV) == 0)
-                     break;
