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 @@ -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 +#include + -+#include ++#include +#include + +#include "net/if.h" @@ -92,12 +101,31 @@ +#include +#include +#include ++#include + +#include + ++#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;