updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / nforce-nvsound / nforce-nvsound.patch
blob8fee72dced95e67fde4886a5fb8d0ab5c6d09554
1 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/Makefile.kbuild NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/Makefile.kbuild
2 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/Makefile.kbuild 2005-10-21 20:59:44.000000000 -0500
3 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/Makefile.kbuild 2008-08-14 10:13:48.000000000 -0500
4 @@ -48,16 +48,16 @@
5 EXTRA_LDFLAGS := -d
7 # Figure out how many args remap_page_ranges() wants or new remap call
8 -ifeq ($(shell sh $(src)/conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" remap_pfn_range), 1)
9 +#ifeq ($(shell sh $(src)/conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" remap_pfn_range), 1)
10 EXTRA_CFLAGS += -DNV_REMAP_PFN_RANGE_PRESENT
11 -else
12 - REMAP_PAGE_RANGE := $(shell sh $(src)/conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" remap_page_range)
14 - ifeq ($(REMAP_PAGE_RANGE),5)
15 - EXTRA_CFLAGS += -DREMAP_NEW
16 - endif
18 -endif
19 +#else
20 +# REMAP_PAGE_RANGE := $(shell sh $(src)/conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" remap_page_range)
22 +# ifeq ($(REMAP_PAGE_RANGE),5)
23 +# EXTRA_CFLAGS += -DREMAP_NEW
24 +# endif
26 +#endif
28 PATCHLEVEL ?= $(shell sh ./conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" kernel_patch_level)
29 ifeq ($(PATCHLEVEL), 4)
30 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/Makefile.kbuild.orig NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/Makefile.kbuild.orig
31 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/Makefile.kbuild.orig 1969-12-31 18:00:00.000000000 -0600
32 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/Makefile.kbuild.orig 2005-10-21 20:59:44.000000000 -0500
33 @@ -0,0 +1,116 @@
35 +# Copyright (c) nVidia Corporation
37 +# Makefile to build nForce main driver with kbuild
40 +MODULE_NAME = nvsound
41 +MODULE = $(MODULE_NAME).ko
43 +SOUND_CORE_OBJ = mcpmain.o
44 +SOUND_GLUE_OBJS = nvalinux.o nvmixer.o nvmain.o
46 +$(MODULE_NAME)-objs := $(SOUND_CORE_OBJ) $(SOUND_GLUE_OBJS)
48 +KERNEL_GLUE_NAME := nvsoundif.o
49 +KERNEL_GLUE_OBJS := $(SOUND_GLUE_OBJS) $(MODULE_NAME).mod.o
51 +src ?= .
52 +obj ?= .
54 +obj-m := $(MODULE_NAME).o
56 +EXTRA_CFLAGS += -I$(src)
57 +EXTRA_CFLAGS += -Wall -Wimplicit -Wreturn-type -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wpointer-arith -Wno-multichar -Werror -O -MD $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-error
59 +ifdef SYSSRC
60 + KERNEL_SOURCES := $(SYSSRC)
61 + KERNEL_HEADERS := $(KERNEL_SOURCES)/include
62 + MODULE_ROOT := /lib/modules/$(shell sh $(src)/conftest.sh $(CC) $(SYSSRC) $(SYSOUT) get_uname)/kernel/sound/oss
63 +else
64 + KERNEL_SOURCES := /lib/modules/$(shell uname -r)/build
65 + KERNEL_HEADERS := $(KERNEL_SOURCES)/include
66 + MODULE_ROOT := /lib/modules/$(shell uname -r)/kernel/sound/oss
67 +endif
69 +ifndef SYSOUT
70 + KERNEL_OUTPUT := $(KERNEL_SOURCES)
71 + KBUILD_PARAMS :=
72 +else
73 + KERNEL_OUTPUT := $(SYSOUT)
74 + KBUILD_PARAMS := KBUILD_OUTPUT=$(KERNEL_OUTPUT)
75 +endif
78 +# NVIDIA binary object file includes .common section.
81 +EXTRA_LDFLAGS := -d
83 +# Figure out how many args remap_page_ranges() wants or new remap call
84 +ifeq ($(shell sh $(src)/conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" remap_pfn_range), 1)
85 + EXTRA_CFLAGS += -DNV_REMAP_PFN_RANGE_PRESENT
86 +else
87 + REMAP_PAGE_RANGE := $(shell sh $(src)/conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" remap_page_range)
89 + ifeq ($(REMAP_PAGE_RANGE),5)
90 + EXTRA_CFLAGS += -DREMAP_NEW
91 + endif
93 +endif
95 +PATCHLEVEL ?= $(shell sh ./conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" kernel_patch_level)
96 +ifeq ($(PATCHLEVEL), 4)
97 + ifeq ($(shell sh ./conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" change_page_attr), 1)
98 + EXTRA_CFLAGS += -DNV_CHANGE_PAGE_ATTR_PRESENT
99 + endif
100 +else
101 + EXTRA_CFLAGS += -DNV_CHANGE_PAGE_ATTR_PRESENT
102 +endif
105 +# KBUILD build parameters.
108 +KBUILD_PARAMS += -C $(KERNEL_SOURCES) SUBDIRS=$(PWD) KBUILD_VERBOSE=1
110 +module: gcc-sanity-check
111 + @make CC=$(CC) $(KBUILD_PARAMS) modules; \
112 + if ! [ -f $(MODULE_OBJECT) ]; then \
113 + echo "$(MODULE_OBJECT) failed to build!"; \
114 + exit 1; \
115 + fi
117 +$(KERNEL_GLUE_NAME): module
118 + $(LD) $(EXTRA_LDFLAGS) -r -o $(KERNEL_GLUE_NAME) $(KERNEL_GLUE_OBJS)
120 +$(obj)/$(SOUND_CORE_OBJ):
121 + cp $(src)/$(SOUND_CORE_OBJ) $(obj)/$(SOUND_CORE_OBJ)
123 +gcc-sanity-check:
124 + @if ! sh $(src)/conftest.sh "$(CC)" "$(KERNEL_SOURCES)" "$(KERNEL_OUTPUT)" cc_sanity_check full_output $(CC); then exit 1; fi
126 +# Installation
127 +TARGET_KERNEL ?= $(shell uname -r)
129 +TARGETDIR = /lib/modules/$(TARGET_KERNEL)/kernel/sound/oss
132 +# Do fake install if not root (needed for building rpms)
133 +install:
134 +ifeq ($(wildcard $(MODULE)), $(MODULE))
135 + mkdir -p $(INSTROOT)/$(TARGETDIR)
136 +ifeq "$(UID)" "0"
137 + install -b -m 755 -o root $(MODULE) $(INSTROOT)/$(TARGETDIR)
138 + /sbin/depmod -a
139 +else
140 + install -b -m 755 $(MODULE) $(INSTROOT)/$(TARGETDIR)
141 +endif # uid is root
142 +endif # module
144 +uninstall:
145 + rm -f $(TARGETDIR)/$(MODULE)
146 + /sbin/depmod -a
148 +clean:
149 + rm -f *.ko *mod.* *.cmd nv*.o *~ core
150 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/conftest.sh NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/conftest.sh
151 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/conftest.sh 2005-10-21 20:59:44.000000000 -0500
152 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/conftest.sh 2008-08-14 10:13:48.000000000 -0500
153 @@ -422,7 +422,7 @@
154 #include <asm/cacheflush.h>
155 #endif
156 int test_cpattr(struct page *pp, int i, pgprot_t prot) {
157 - return change_page_attr(pp, i, prot);
158 + return set_pages_uc(pp, i);
159 }" > conftest$$.c
161 $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
162 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/conftest.sh.orig NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/conftest.sh.orig
163 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/conftest.sh.orig 1969-12-31 18:00:00.000000000 -0600
164 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/conftest.sh.orig 2005-10-21 20:59:44.000000000 -0500
165 @@ -0,0 +1,483 @@
166 +#!/bin/bash
168 +# make sure we are in the directory containing this script
169 +SCRIPTDIR=`dirname $0`
170 +cd $SCRIPTDIR
171 +PATH="${PATH}:/bin:/sbin"
173 +CC="$1"
174 +ISYSTEM=`$CC -print-file-name=include`
175 +SOURCES=$2
176 +HEADERS=$SOURCES/include
177 +OUTPUT=$3
179 +CFLAGS="-D__KERNEL__ \
180 +-nostdinc -isystem $ISYSTEM \
181 +-Werror -Wimplicit-function-declaration"
183 +if [ "$OUTPUT" != "$SOURCES" ]; then
184 + CFLAGS="$CFLAGS -I$OUTPUT/include2 -I$OUTPUT/include \
185 +-I$HEADERS -I$HEADERS/asm/mach-default"
186 +else
187 + CFLAGS="$CFLAGS -I$HEADERS -I$HEADERS/asm/mach-default"
190 +case "$4" in
191 + remap_page_range)
193 + # Determine the number of arguments expected by remap_page_range.
196 + echo "#include <linux/mm.h>
197 + int do_test_remap_page_range(void) {
198 + pgprot_t pgprot;
199 + remap_page_range(NULL, 0L, 0L, 0L, pgprot);
200 + }" > conftest$$.c
202 + $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
203 + rm -f conftest$$.c
205 + if [ -f conftest$$.o ]; then
206 + echo "5"
207 + rm -f conftest$$.o
208 + exit 0
209 + fi
211 + echo "#include <linux/mm.h>
212 + int do_test_remap_page_range(void) {
213 + pgprot_t pgprot;
214 + remap_page_range(0L, 0L, 0L, pgprot);
215 + }" > conftest$$.c
217 + $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
218 + rm -f conftest$$.c
220 + if [ -f conftest$$.o ]; then
221 + echo "4"
222 + rm -f conftest$$.o
223 + exit 0
224 + else
226 + # We couldn't determine the number of arguments expected by the
227 + # remap_page_range function.
229 + exit 1
230 + fi
231 + ;;
233 + cc_sanity_check)
235 + # Verify that the same compiler is used for the kernel and kernel
236 + # module.
238 + VERBOSE=$5
240 + if test -n "$IGNORE_CC_MISMATCH" -o -n "$SYSSRC" -o -n "$SYSINCLUDE"; then
242 + # The user chose to disable the CC sanity test (which may or
243 + # may not be wise) or is building the module for a kernel not
244 + # currently running, which renders our test meaningless.
246 + exit 0
247 + fi
249 + # usage: conftest.sh [cc_sanity_check] [full_output|just_msg] [$CC]
251 + rm -f gcc-version-check
252 + $CC gcc-version-check.c -o gcc-version-check > /dev/null 2>&1
253 + if [ -f gcc-version-check ]; then
254 + PROC_VERSION=`cat /proc/version`
255 + MSG=`./gcc-version-check "$PROC_VERSION"`
256 + RET=$?
257 + rm -f gcc-version-check
258 + else
259 + MSG="Could not compile gcc-version-check.c"
260 + RET=1
261 + fi
263 + if [ "$RET" != "0" ]; then
265 + # The gcc version check failed
268 + if [ "$VERBOSE" = "full_output" ]; then
269 + echo "";
270 + echo "gcc-version-check failed:";
271 + echo "";
272 + echo "$MSG" | fmt -w 60
273 + echo "";
274 + echo "If you know what you are doing and want to override";
275 + echo "the gcc version check, you can do so by setting the";
276 + echo "IGNORE_CC_MISMATCH environment variable to \"1\".";
277 + echo "";
278 + echo "In any other case, set the CC environment variable";
279 + echo "to the name of the compiler that was used to compile";
280 + echo "the kernel.";
281 + echo ""
282 + echo -e "*** Failed cc sanity check. Bailing out! ***";
283 + echo "";
284 + else
285 + echo "$MSG"
286 + fi
287 + exit 1;
288 + else
289 + exit 0
290 + fi
291 + ;;
293 + kernel_patch_level)
295 + # Determine the kernel's major patch level; this is only done if we
296 + # aren't told by KBUILD.
299 + echo $(grep "^PATCHLEVEL =" $SOURCES/Makefile | cut -d " " -f 3)
300 + exit 0
301 + ;;
303 + suser_sanity_check)
305 + # Determine the caller's user id to determine if we have sufficient
306 + # privileges for the requested operation.
308 + if test $(id -ur) != 0; then
309 + echo "";
310 + echo "Please run \"make install\" as root.";
311 + echo "";
312 + echo -e "*** Failed super-user sanity check. Bailing out! ***";
313 + exit 1
314 + else
315 + exit 0
316 + fi
317 + ;;
319 + rmmod_sanity_check)
321 + # Make sure that any currently loaded NVIDIA kernel module can be
322 + # unloaded.
324 + MODULE="nvidia"
326 + if test -n "$SYSSRC" -o -n "$SYSINCLUDE"; then
328 + # Don't attempt to remove the kernel module if we're not
329 + # building against the running kernel.
331 + exit 0
332 + fi
334 + if lsmod | grep -wq $MODULE; then
335 + rmmod $MODULE >& /dev/null
336 + fi
338 + if lsmod | grep -wq $MODULE; then
340 + # The NVIDIA kernel module is still loaded, most likely because
341 + # it is busy.
343 + echo "";
344 + echo "Unable to remove existing NVIDIA kernel module.";
345 + echo "Please be sure you have exited X before attempting";
346 + echo "to install the NVIDIA kernel module.";
347 + echo "";
348 + echo -e "*** Failed rmmod sanity check. Bailing out! ***";
349 + exit 1
350 + else
351 + exit 0
352 + fi
353 + ;;
355 + select_makefile)
357 + # Select which Makefile to use based on the version of the
358 + # kernel we are building against: use the kbuild Makefile for
359 + # 2.6 and newer kernels, and the old Makefile for kernels older
360 + # than 2.6.
362 + rm -f Makefile
363 + RET=1
364 + VERBOSE=$5
365 + FILE="linux/version.h"
367 + if [ -f $HEADERS/$FILE -o -f $OUTPUT/include/$FILE ]; then
369 + # We are either looking at a configured kernel source
370 + # tree or at headers shipped for a specific kernel.
371 + # Determine the kernel version using a compile check.
373 + echo "#include \"linux/version.h\"
374 + int main() {
375 + if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) {
376 + return 0;
377 + } else {
378 + return 1;
380 + }" > conftest$$.c
382 + gcc conftest$$.c -o conftest$$ -nostdinc -I $HEADERS > /dev/null 2>&1
383 + rm -f conftest$$.c
385 + if [ -f conftest$$ ]; then
386 + ./conftest$$ > /dev/null 2>&1
387 + if [ $? = "0" ]; then
388 + ln -s Makefile.kbuild Makefile
389 + else
390 + ln -s Makefile.nvidia Makefile
391 + fi
392 + rm -f conftest$$
393 + RET=0
394 + fi
395 + else
396 + MAKEFILE=$HEADERS/../Makefile
397 + CONFIG=$HEADERS/../.config
399 + if [ -f $MAKEFILE -a -f $CONFIG ]; then
401 + # This source tree is not configured, but includes
402 + # a Makefile and a .config file. If this is a 2.6
403 + # kernel older than 2.6.6, that's all we require to
404 + # build our module.
406 + PATCHLEVEL=$(grep "^PATCHLEVEL =" $MAKEFILE | cut -d " " -f 3)
407 + SUBLEVEL=$(grep "^SUBLEVEL =" $MAKEFILE | cut -d " " -f 3)
409 + if [ $PATCHLEVEL -ge 6 -a $SUBLEVEL -le 5 ]; then
410 + ln -s Makefile.kbuild Makefile
411 + RET=0
412 + fi
413 + fi
414 + fi
416 + if [ "$RET" != "0" ]; then
417 + echo "";
418 + echo "If you are using a Linux 2.4 kernel, please make sure";
419 + echo "you either have configured kernel sources matching your";
420 + echo "kernel or the correct set of kernel headers installed";
421 + echo "on your system.";
422 + echo "";
423 + echo "If you are using a Linux 2.6 kernel, please make sure";
424 + echo "you have configured kernel sources matching your kernel";
425 + echo "installed on your system. If you specified a separate";
426 + echo "output directory using either the \"KBUILD_OUTPUT\" or";
427 + echo "the \"O\" KBUILD parameter, make sure to specify this";
428 + echo "directory with the SYSOUT environment variable or with";
429 + echo "the appropriate nvidia-installer command line option.";
430 + echo "";
431 + if [ "$VERBOSE" = "full_output" ]; then
432 + echo "*** Unable to determine the target kernel version. ***";
433 + echo "";
434 + fi
435 + exit 1
436 + else
437 + exit 0
438 + fi
439 + ;;
441 + get_uname)
443 + # print UTS_RELEASE from the kernel sources that we are building
444 + # against; if an error occurs, give up and just return `uname -r`
447 + echo "#include \"linux/version.h\"
448 + int main() {
449 + printf(\"%s\n\", UTS_RELEASE);
450 + return 0;
451 + }" > conftest$$.c
453 + CC $CFLAGS -o conftest$$ conftest$$.c > /dev/null 2>&1
454 + rm -f conftest$$.c
456 + if [ -f conftest$$ ]; then
457 + ./conftest$$
458 + rm -f conftest$$
459 + exit 0
460 + else
461 + uname -r
462 + exit 1
463 + fi
464 + ;;
466 + rivafb_sanity_check)
468 + # Check if the kernel was compiled with rivafb support. If so, then
469 + # exit, since our driver no longer works with rivafb.
471 + RET=1
472 + VERBOSE=$5
473 + FILE="linux/autoconf.h"
475 + if [ -f $HEADERS/$FILE -o -f $OUTPUT/include/$FILE ]; then
477 + # We are looking at a configured source tree; verify
478 + # that its configuration doesn't include rivafb using
479 + # a compile check.
481 + echo "#include \"linux/autoconf.h\"
482 + #ifdef CONFIG_FB_RIVA
483 + #error CONFIG_FB_RIVA defined!!
484 + #endif
485 + " > conftest$$.c
487 + $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
488 + rm -f conftest$$.c
490 + if [ -f conftest$$.o ]; then
491 + rm -f conftest$$.o
492 + RET=0
493 + fi
494 + else
495 + CONFIG=$HEADERS/../.config
496 + if [ -f $CONFIG ]; then
497 + if [ -z "$(grep "^CONFIG_FB_RIVA=y" $CONFIG)" ]; then
498 + RET=0
499 + fi
500 + fi
501 + fi
503 + if [ "$RET" != "0" ]; then
504 + echo "Your kernel was configured to include rivafb support!";
505 + echo "";
506 + echo "The rivafb driver conflicts with the NVIDIA driver, please";
507 + echo "reconfigure your kernel and *disable* rivafb support, then";
508 + echo "try installing the NVIDIA kernel module again.";
509 + echo "";
510 + if [ "$VERBOSE" = "full_output" ]; then
511 + echo -e "*** Failed rivafb sanity check. Bailing out! ***";
512 + echo "";
513 + fi
514 + exit 1
515 + else
516 + exit 0
517 + fi
518 + ;;
520 + rivafb_module_sanity_check)
522 + # Check if the kernel was compiled with rivafb support as a module.
523 + # If so, notify the user that the two are not compatible. Don't
524 + # fail in this case, as many distros are likely to include this as
525 + # a module.
527 + RET=1
528 + VERBOSE=$4
529 + FILE="linux/autoconf.h"
531 + if [ -f $HEADERS/$FILE -o -f $OUTPUT/include/$FILE ]; then
533 + # We are looking at a configured source tree; verify
534 + # that its configuration doesn't include rivafb using
535 + # a compile check.
537 + echo "#include \"linux/autoconf.h\"
538 + #ifdef CONFIG_FB_RIVA_MODULE
539 + #error CONFIG_FB_RIVA_MODULE defined!!
540 + #endif
541 + " > conftest$$.c
543 + $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
544 + rm -f conftest$$.c
546 + if [ -f conftest$$.o ]; then
547 + rm -f conftest$$.o
548 + RET=0
549 + fi
550 + else
551 + CONFIG=$HEADERS/../.config
552 + if [ -f $CONFIG ]; then
553 + if [ -z "$(grep "^CONFIG_FB_RIVA=m" $CONFIG)" ]; then
554 + RET=0
555 + fi
556 + fi
557 + fi
559 + if [ "$RET" != "0" ]; then
560 + echo "";
561 + echo "Your kernel was configured to include rivafb support as";
562 + echo "a loadable kernel module.";
563 + echo "";
564 + echo "The rivafb driver conflicts with the NVIDIA driver; the";
565 + echo "NVIDIA kernel module will still be built and installed,";
566 + echo "but be aware that the NVIDIA driver will not be able to";
567 + echo "function properly if the rivafb module is loaded!";
568 + echo "";
569 + if [ "$VERBOSE" = "full_output" ]; then
570 + echo -en "*** Failed rivafb module sanity check, but ";
571 + echo -e "continuing! ***";
572 + echo "";
573 + fi
574 + fi
576 + exit 0
577 + ;;
579 + change_page_attr)
581 + # Determine if change_page_attr() is present
584 + echo "#include <linux/version.h>
585 + #include <linux/mm.h>
586 + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
587 + #include <asm/cacheflush.h>
588 + #endif
589 + int test_cpattr(struct page *pp, int i, pgprot_t prot) {
590 + return change_page_attr(pp, i, prot);
591 + }" > conftest$$.c
593 + $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
594 + rm -f conftest$$.c
596 + if [ -f conftest$$.o ]; then
597 + rm -f conftest$$.o
598 + echo 1
599 + else
600 + echo 0
601 + fi
602 + ;;
604 + class_simple_create)
606 + # Determine if class_simple_create() is present.
609 + echo "#include <linux/device.h>
610 + struct class_simple*
611 + test_class_create(struct module *owner, char *name) {
612 + return class_simple_create(owner, name);
613 + }" > conftest$$.c
615 + $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
616 + rm -f conftest$$.c
618 + if [ -f conftest$$.o ]; then
619 + rm -f conftest$$.o
620 + echo 1
621 + else
622 + echo 0
623 + fi
624 + ;;
626 + remap_pfn_range)
628 + # Determine if remap_page_range() is present.
631 + echo "#include <linux/mm.h>
632 + int nv_remap_pfn_range(void) {
633 + pgprot_t pgprot = __pgprot(0);
634 + remap_pfn_range(NULL, 0L, 0L, 0L, pgprot);
635 + }" > conftest$$.c
637 + $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
638 + rm -f conftest$$.c
640 + if [ -f conftest$$.o ]; then
641 + rm -f conftest$$.o
642 + echo 1
643 + else
644 + echo 0
645 + fi
646 + ;;
648 +esac
649 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvaioctl.h NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvaioctl.h
650 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvaioctl.h 2005-10-21 20:59:44.000000000 -0500
651 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvaioctl.h 2008-08-14 10:13:48.000000000 -0500
652 @@ -215,7 +215,7 @@
653 CODEC_CAPS
656 -enum device_type{
657 +enum dev_type{
658 APU_DEVICE = 1,
659 VAPU_DEVICE,
660 ACI_DEVICE
661 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvaioctl.h.orig NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvaioctl.h.orig
662 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvaioctl.h.orig 1969-12-31 18:00:00.000000000 -0600
663 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvaioctl.h.orig 2005-10-21 20:59:44.000000000 -0500
664 @@ -0,0 +1,267 @@
665 +////////////////////////////////////////////////////////////////////////
667 +// nvaioctl.h
669 +// Descripion - Header file used for the common structures for the
670 +// ioctls used for apps and driver
672 +// Copyright (c) 2004-2005 NVIDIA Corporation
674 +////////////////////////////////////////////////////////////////////////
676 +#ifndef _NVA_IOCTL_H_
677 +#define _NVA_IOCTL_H_
680 +//*****************************************************************************
681 +// Mixer Nodes
682 +//*****************************************************************************
683 +// These are the mixer topology nodes.
685 +typedef enum
687 + MXR_NODE_PCBEEP_VOLUME = 0,
688 + MXR_NODE_PCBEEP_MUTE, //1
690 + MXR_NODE_PHONE_VOLUME, //2
691 + MXR_NODE_PHONE_MUTE, //3
693 + MXR_NODE_MIC_BOOST, //4
694 + MXR_NODE_MIC_SELECT, //5
695 + MXR_NODE_MIC_VOLUME, //6
696 + MXR_NODE_MIC_MUTE, //7
698 + MXR_NODE_LINEIN_VOLUME, //8
699 + MXR_NODE_LINEIN_MUTE, //9
701 + MXR_NODE_CD_VOLUME, //10
702 + MXR_NODE_CD_MUTE, //11
704 + MXR_NODE_VIDEO_VOLUME, //12
705 + MXR_NODE_VIDEO_MUTE, //13
707 + MXR_NODE_AUX_VOLUME, //14
708 + MXR_NODE_AUX_MUTE, //15
710 + RESERVED_16, //16
711 + RESERVED_17, //17
713 + RESERVED_18, //18
714 + MXR_NODE_CONVERT_LINEIN_REAR, //19
715 + MXR_NODE_CONVERT_MIC_CENTERLFE, //20
716 + MXR_NODE_SWAP_CENTERLFE, //21
717 + MXR_NODE_MASTER_VOLUME, //22
718 + MXR_NODE_MASTER_MUTE, //23
721 + MXR_NODE_WAVEIN_MIC_VOLUME, //24
722 + MXR_NODE_WAVEIN_CD_VOLUME, //25
723 + MXR_NODE_WAVEIN_VIDEO_VOLUME, //26
724 + MXR_NODE_WAVEIN_AUX_VOLUME, //27
725 + MXR_NODE_WAVEIN_LINEIN_VOLUME, //28
726 + MXR_NODE_WAVEIN_STEREO_MIX_VOLUME, //29
727 + MXR_NODE_WAVEIN_MONO_MIX_VOLUME, //30
728 + MXR_NODE_WAVEIN_PHONE_VOLUME, //31
729 + MXR_NODE_WAVEIN_SPDIFIN_VOLUME, //32
730 + MXR_NODE_WAVEIN_SELECT, //33
733 + RESERVED_34, //34
734 + MXR_NODE_LINEOUT_VOLUME, //35
735 + MXR_NODE_LINEOUT_MUTE, //36
738 + RESERVED_37, //37
739 + MXR_NODE_HEADPHONE_VOLUME, //38
740 + MXR_NODE_HEADPHONE_MUTE, //39
742 + MXR_NODE_SPDIF, //40
743 + RESERVED_41, //41
744 + MXR_NODE_SPDIF_VOLUME, //42
745 + MXR_NODE_SPDIF_MUTE, //43
747 + MXR_NODE_DIGITIZED_INPUT_SELECT, //44
748 + MXR_NODE_DIGITIZED_INPUT_VOLUME, //45
749 + MXR_NODE_DIGITIZED_INPUT_MUTE, //46
750 + MXR_NODE_DIGITIZED_INPUT_FX, //47
753 + MXR_NODE_MONOOUT_MONO_MIX_VOLUME, //48
754 + MXR_NODE_MONOOUT_MIC_VOLUME, //49
755 + MXR_NODE_MONOOUT_SELECT, //50
758 + MXR_NODE_MICIN_VOLUME, //51
759 + MXR_NODE_MICIN_MUTE, //52
761 + MXR_NODE_FRONT_VOLUME, //53
762 + MXR_NODE_FRONT_MUTE, //54
763 + MXR_NODE_SURROUND_VOLUME, //55
764 + MXR_NODE_SURROUND_MUTE, //56
765 + MXR_NODE_CENTER_VOLUME, //57
766 + MXR_NODE_CENTER_MUTE, //58
767 + MXR_NODE_LFE_VOLUME, //59
768 + MXR_NODE_LFE_MUTE, //60
769 + MXR_NODE_BASS, //61
770 + MXR_NODE_TREBLE, //62
772 + MXR_NODE_3D_ENVIRONMENT_VOLUME, //63
773 + MXR_NODE_3D_ENVIRONMENT_MUTE, //64
775 + MXR_NODE_INVALID //65
777 +} MXR_NODE, *PMXR_NODE;
779 +#define FIRST_MXR_NODE MXR_NODE_PCBEEP_VOLUME
780 +#define LAST_MXR_NODE MXR_NODE_MICIN_MUTE
781 +#define NUM_MXR_NODES MXR_NODE_INVALID
784 +enum Premix_regs{
785 + PREMIX_LEFT=0,
786 + PREMIX_RIGHT,
787 + PREMIX_CENTER,
788 + PREMIX_SUB,
789 + PREMIX_RLEFT,
790 + PREMIX_RRIGHT,
791 + PREMIX_LEFT_SURR,
792 + PREMIX_RIGHT_SURR
795 +typedef struct _nva_ioctl{
796 + void* pindata;
797 + void* poutdata;
798 + char name[20];
799 + unsigned int cmd;
800 + unsigned int subcmd;
801 + unsigned int indata[4];
802 + unsigned int outdata[4];
803 + float pfoutdata;
804 + unsigned int inlength;
805 + unsigned int outlength;
806 +}NVA_IOCTL, *PNVA_IOCTL;
809 +#define NV_IOC_MAGIC 'n'
810 +#define NV_IOCRESET _IO(NV_IOC_MAGIC, 0)
812 +#define NV_AC97CODEC_READ _IOR(NV_IOC_MAGIC,1,NVA_IOCTL)
813 +#define NV_AC97CODEC_WRITE _IOW(NV_IOC_MAGIC,2,NVA_IOCTL)
814 +#define NV_AC97CON_READ _IOR(NV_IOC_MAGIC,3,NVA_IOCTL)
815 +#define NV_AC97CON_WRITE _IOW(NV_IOC_MAGIC,4,NVA_IOCTL)
816 +#define NV_SET_SPKRSELECT _IOW(NV_IOC_MAGIC,5,NVA_IOCTL)
817 +#define NV_GET_SPKRSELECT _IOR(NV_IOC_MAGIC,6,NVA_IOCTL)
818 +#define NV_SET_ANALOGOUT _IOW(NV_IOC_MAGIC,7,NVA_IOCTL)
819 +#define NV_GET_ANALOGOUT _IOR(NV_IOC_MAGIC,8,NVA_IOCTL)
820 +#define NV_SET_DIGITALOUT _IOW(NV_IOC_MAGIC,9,NVA_IOCTL)
821 +#define NV_GET_DIGITALOUT _IOR(NV_IOC_MAGIC,10,NVA_IOCTL)
822 +#define NV_SET_ENCODING _IOW(NV_IOC_MAGIC,11,NVA_IOCTL)
823 +#define NV_GET_ENCODING _IOR(NV_IOC_MAGIC,12,NVA_IOCTL)
824 +#define NV_SET_PREMIXVOL _IOW(NV_IOC_MAGIC,13,NVA_IOCTL)
825 +#define NV_GET_PREMIXVOL _IOR(NV_IOC_MAGIC,14,NVA_IOCTL)
826 +#define NV_GET_INFO _IOR(NV_IOC_MAGIC,15,NVA_IOCTL)
827 +#define NV_SET_MIXERMUTE _IOW(NV_IOC_MAGIC,16,NVA_IOCTL)
828 +#define NV_GET_MIXERMUTE _IOR(NV_IOC_MAGIC,17,NVA_IOCTL)
829 +#define NV_GET_ONOFF _IOR(NV_IOC_MAGIC,18,NVA_IOCTL)
830 +#define NV_SET_ONOFF _IOW(NV_IOC_MAGIC,19,NVA_IOCTL)
831 +#define NV_GET_EQPRESET _IOR(NV_IOC_MAGIC,20,NVA_IOCTL)
832 +#define NV_SET_EQPRESET _IOW(NV_IOC_MAGIC,21,NVA_IOCTL)
833 +#define NV_GET_EQINFO _IOR(NV_IOC_MAGIC,22,NVA_IOCTL)
834 +#define NV_GET_EQDATA _IOR(NV_IOC_MAGIC,23,NVA_IOCTL)
835 +#define NV_SET_EQDATA _IOW(NV_IOC_MAGIC,24,NVA_IOCTL)
836 +#define NV_SET_AMPLIFIER _IOW(NV_IOC_MAGIC,25,NVA_IOCTL)
838 +#define NV_IOC_HARDRESET _IO(NV_IOC_MAGIC, 26)
840 +#define NV_IOC_MAXNR NV_IOC_HARDRESET
842 +typedef enum {
843 + NV_SPKR_HEAD = 0,
844 + NV_SPKR_STEREO,
845 + NV_SPKR_QUAD,
846 + NV_SPKR_5POINT1,
847 + NV_SPKR_7POINT1
848 +}NV_SPKR_SEETINGS;
850 +typedef enum {
851 + ANALOG_OUT = 0,
852 + DIGITAL_OUT,
853 + MIC_BOOST,
854 + SWAP_LINEIN,
855 + SWAP_MICIN,
856 + SWAP_CENTERLFE,
857 + ALTER_MIC,
858 + GLOBAL_EQ
859 +}ON_OFFPARAMS;
861 +enum encoding_options{
862 + EN_NONE = 0,
863 + EN_CLONE,
864 + EN_DELAY,
865 + EN_TIME,
866 + EN_PRESET,
867 + EN_LFECROSSOVER,
868 + EN_LFECROSSOVERRANGE
871 +enum info_options{
872 + PRODUCT_NAME = 0,
873 + HW_MODEL,
874 + HW_REV,
875 + DRIVER_VERSION,
876 + KERNEL_VERSION,
877 + CODEC_NAME,
878 + CODEC_MODEL,
879 + CODEC_CAPS
882 +enum device_type{
883 + APU_DEVICE = 1,
884 + VAPU_DEVICE,
885 + ACI_DEVICE
889 +// Defined Presets for Global EQ
890 +// Use Custom to set user defined Values
892 +typedef enum
894 + GBEQ_FLAT = 0,
895 + GBEQ_CLASSICAL,
896 + GBEQ_CLUB,
897 + GBEQ_DANCE,
898 + GBEQ_FULLBASS,
899 + GBEQ_FULLBASSANDTREBLE,
900 + GBEQ_FULLTREBLE,
901 + GBEQ_HEADPHONES,
902 + GBEQ_LARGEHALL,
903 + GBEQ_LIVE,
904 + GBEQ_OLDTIMERADIO,
905 + GBEQ_PARTY,
906 + GBEQ_POP,
907 + GBEQ_REGGAE,
908 + GBEQ_ROCK,
909 + GBEQ_SOFT,
910 + GBEQ_SOFTROCK,
911 + GBEQ_TECHNO,
912 + GBEQ_CUSTOM // This on is always last
913 +} GBEQ_PRESETS, *PGBEQ_PRESETS;
916 +// Possible Frequency Range allowed for EQ bands
919 +enum{
920 + GBEQ_FREQ63 = 0,
921 + GBEQ_FREQ125,
922 + GBEQ_FREQ250,
923 + GBEQ_FREQ500,
924 + GBEQ_FREQ1K,
925 + GBEQ_FREQ2K,
926 + GBEQ_FREQ4K,
927 + GBEQ_FREQ8K,
928 + GBEQ_FREQ16K
931 +#endif
932 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvalinux.c NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvalinux.c
933 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvalinux.c 2005-10-21 20:59:44.000000000 -0500
934 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvalinux.c 2008-08-14 10:13:48.000000000 -0500
935 @@ -60,10 +60,14 @@
936 #define SET_FPU_INUSE(x) ((x->flags) |= PF_USEDFPU)
937 #define CLEAR_FPU_INUSE(x) ((x->flags) &= ~PF_USEDFPU)
938 #define IS_FPU_INUSE(x) ((x->flags) & PF_USEDFPU)
939 -#else
940 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
941 #define SET_FPU_INUSE(x) ((x->thread_info->status) |= TS_USEDFPU)
942 #define CLEAR_FPU_INUSE(x) ((x->thread_info->status) &= ~TS_USEDFPU)
943 #define IS_FPU_INUSE(x) ((x->thread_info->status) & TS_USEDFPU)
944 +#else
945 +#define SET_FPU_INUSE(x) ((task_thread_info(x)->status) |= TS_USEDFPU)
946 +#define CLEAR_FPU_INUSE(x) ((task_thread_info(x)->status) &= ~TS_USEDFPU)
947 +#define IS_FPU_INUSE(x) ((task_thread_info(x)->status) & TS_USEDFPU)
948 #endif
950 #include "nvavm.h"
951 @@ -182,11 +186,11 @@
952 if ( cpu_has_fxsr ) {
953 __asm__ __volatile__( "fxsave %0\n"
954 "fnclex"
955 - :"=m"(currenttask->thread.i387.fxsave) );
956 + :"=m"(currenttask->thread.xstate->fxsave) );
957 } else {
958 __asm__ __volatile__( "fnsave %0\n"
959 "fwait"
960 - :"=m"(currenttask->thread.i387.fsave) );
961 + :"=m"(currenttask->thread.xstate->fsave) );
963 CLEAR_FPU_INUSE(currenttask);
965 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvalinux.c.orig NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvalinux.c.orig
966 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvalinux.c.orig 1969-12-31 18:00:00.000000000 -0600
967 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvalinux.c.orig 2005-10-21 20:59:44.000000000 -0500
968 @@ -0,0 +1,1358 @@
969 +/*
971 + * Copyright 2003-2004 by NVIDIA Corporation. All rights reserved. All
972 + * information contained herein is proprietary and confidential to NVIDIA
973 + * Corporation. Any use, reproduction, or disclosure without the written
974 + * permission of NVIDIA Corporation is prohibited.
975 + *
976 + */
979 +* nvalinux.c
981 +* Implementation of functions calling kenrel functions
985 +#define __NO_VERSION_
986 +#include <linux/version.h>
987 +#include <linux/module.h>
988 +#include <linux/kernel.h>
989 +#include <linux/init.h>
990 +#include <linux/types.h>
991 +#include <linux/slab.h>
992 +#include <linux/vmalloc.h>
993 +#include <asm/io.h>
994 +#include <linux/string.h>
995 +#include <linux/spinlock.h>
996 +#include <linux/delay.h>
997 +#include <linux/pci.h>
998 +#include <linux/interrupt.h>
999 +#include <asm/uaccess.h>
1001 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
1002 +#include <linux/wrapper.h>
1003 +#endif
1005 +#include <linux/highmem.h>
1006 +#include <asm/pgtable.h>
1008 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
1009 +#define NV_MAY_SLEEP() (!in_interrupt())
1010 +#else
1011 +#define NV_MAY_SLEEP() (!in_interrupt() && !in_atomic())
1012 +#endif
1014 +#if defined (__i386__) || defined (__x86_64__)
1015 +#include <asm/i387.h>
1016 +#endif
1017 +#include "nvalinux.h"
1019 +#if !defined ASSERT
1020 +#define ASSERT(expr) do { \
1021 + if(!(expr)){\
1022 + printk("Nvsound: Assertion [%s] failed %s:%s(line=%d)\n",\
1023 + #expr,__FILE__,__FUNCTION__,__LINE__);\
1024 + }}while(0)
1025 +#endif
1027 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
1028 +#define SET_FPU_INUSE(x) ((x->flags) |= PF_USEDFPU)
1029 +#define CLEAR_FPU_INUSE(x) ((x->flags) &= ~PF_USEDFPU)
1030 +#define IS_FPU_INUSE(x) ((x->flags) & PF_USEDFPU)
1031 +#else
1032 +#define SET_FPU_INUSE(x) ((x->thread_info->status) |= TS_USEDFPU)
1033 +#define CLEAR_FPU_INUSE(x) ((x->thread_info->status) &= ~TS_USEDFPU)
1034 +#define IS_FPU_INUSE(x) ((x->thread_info->status) & TS_USEDFPU)
1035 +#endif
1037 +#include "nvavm.h"
1039 +static struct pci_dev * pAci_device;
1040 +static struct pci_dev * pApu_device;
1041 +static DEVICE_RESOURCES apu_res;
1043 +static spinlock_t global_spinlock = SPIN_LOCK_UNLOCKED;
1044 +static unsigned long global_flags = 0;
1047 +// Array used to save the FP reg values for local use
1049 +#define NV_MAX_FPLOOP 5
1050 +#if defined (__i386__)
1051 +static struct i387_fsave_struct nvfnSave[NV_MAX_FPLOOP];
1052 +#else
1053 +static struct i387_fxsave_struct nvfxSave[NV_MAX_FPLOOP];
1054 +#endif
1056 +static int nvfpused[NV_MAX_FPLOOP] = {0};
1058 +static VOID * ApuLinearAddress = 0;
1060 +static unsigned int setvapu = 0;
1062 +#ifdef __cplusplus
1063 +extern "C" {
1064 +#endif
1066 +#if defined (__i386__)
1067 +//*****************************************************************************
1068 +// _get_phys_address
1069 +// virtual address to physical page address
1070 +//*****************************************************************************
1072 +static unsigned long
1073 +_get_phys_address(
1074 + unsigned long address,
1075 + int kern
1078 + struct mm_struct *mm;
1079 + pgd_t *pgd = NULL;
1080 + pmd_t *pmd = NULL;
1081 + pte_t *pte = NULL;
1082 + unsigned long retval;
1084 + mm = (kern) ? &init_mm : current->mm;
1085 + spin_lock(&mm->page_table_lock);
1087 + pgd = NV_PGD_OFFSET(address, kern, mm);
1088 + if (!NV_PGD_PRESENT(pgd))
1089 + goto failed;
1091 + pmd = NV_PMD_OFFSET(address, pgd);
1092 + if (!NV_PMD_PRESENT(pmd))
1093 + goto failed;
1095 + pte = NV_PTE_OFFSET(address, pmd);
1096 + if (!NV_PTE_PRESENT(pte))
1097 + goto failed;
1099 + retval = ((NV_PTE_VALUE(pte) & PAGE_MASK) | NV_MASK_OFFSET(address));
1101 + spin_unlock(&mm->page_table_lock);
1102 + return retval;
1104 +failed:
1105 + spin_unlock(&mm->page_table_lock);
1106 + return 0;
1109 +//*****************************************************************************
1110 +// nv_get_kern_phys_address
1111 +//*****************************************************************************
1112 +static unsigned long nv_get_kern_phys_address(
1113 + unsigned long address
1116 + // make sure this address is a kernel pointer
1117 +#if !defined(CONFIG_X86_4G)
1118 + if (address < PAGE_OFFSET)
1120 + printk("user address passed to get_kern_phys_address: 0x%lx\n",
1121 + address);
1122 + return 0;
1124 +#endif
1126 + /* direct-mapped kernel address */
1127 + if ((address > PAGE_OFFSET) && (address < VMALLOC_START))
1128 + return __pa(address);
1130 + return _get_phys_address(address, 1);
1132 +#endif
1133 +//*****************************************************************************
1134 +// AosFpuSave
1135 +//*****************************************************************************
1136 +VOID NV_API_CALL AosFpuSave(int *pTag)
1138 + int count = 0;
1139 + // get the current process
1140 + struct task_struct *currenttask = current;
1142 +#if defined (__i386__)
1144 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,68)
1145 + preempt_disable();
1146 +#endif
1148 + // check for FPU used flags
1149 + if (IS_FPU_INUSE(currenttask)) {
1150 + if ( cpu_has_fxsr ) {
1151 + __asm__ __volatile__( "fxsave %0\n"
1152 + "fnclex"
1153 + :"=m"(currenttask->thread.i387.fxsave) );
1154 + } else {
1155 + __asm__ __volatile__( "fnsave %0\n"
1156 + "fwait"
1157 + :"=m"(currenttask->thread.i387.fsave) );
1159 + CLEAR_FPU_INUSE(currenttask);
1161 + else {
1162 + clts();
1165 +#else
1166 + kernel_fpu_begin();
1167 +#endif
1169 + while(count < NV_MAX_FPLOOP) {
1170 + if(nvfpused[count] == 0) break;
1171 + count = count + 1;
1173 + nvfpused[count] = 1;
1174 +#if defined (__i386__)
1175 + asm volatile("fnsave %0;fnclex; fwait" : "=m"(nvfnSave[count]));
1176 +#else
1177 + asm volatile("fxsave %0;fnclex; fwait" : "=m"(nvfxSave[count]));
1178 +#endif
1179 + *pTag = count;
1181 + if(setvapu) {
1182 + SET_FPU_INUSE(currenttask);
1187 +//*****************************************************************************
1188 +// AosFpuRestore
1189 +//*****************************************************************************
1190 +VOID NV_API_CALL AosFpuRestore(int pTag)
1192 + struct task_struct *currenttask = current;
1193 + if(pTag > -1){
1194 +#if defined (__i386__)
1195 + asm volatile("frstor %0" : : "m" (nvfnSave[pTag]));
1196 +#else
1197 + asm volatile("fxrstor %0" : : "m" (nvfxSave[pTag]));
1198 +#endif
1199 + nvfpused[pTag] = 0;
1201 + if(setvapu && (pTag == 0)) {
1202 + if (IS_FPU_INUSE(currenttask)) {
1203 + CLEAR_FPU_INUSE(currenttask);
1207 + kernel_fpu_end();
1210 +//*****************************************************************************
1211 +// AosMemoryAlloc
1212 +//*****************************************************************************
1213 +VOID * NV_API_CALL AosMemoryAlloc
1215 + IN PAOS_CONTEXT pAosContext,
1216 + IN ULONG Size
1219 + void * pAddress = 0;
1220 + pAddress = kmalloc( (size_t)Size, GFP_KERNEL);
1221 + if(pAddress){
1222 + memset(pAddress,'\0',Size);
1224 + return (pAddress);
1227 +//*****************************************************************************
1228 +// AosMemoryAllocVM
1229 +//*****************************************************************************
1230 +VOID * NV_API_CALL AosMemoryAllocVM
1232 + IN PAOS_CONTEXT pAosContext,
1233 + IN ULONG Size
1236 + void * pAddress = 0;
1237 + if(NV_MAY_SLEEP()) {
1238 + pAddress = vmalloc_32(Size);
1240 + if(pAddress){
1241 + memset(pAddress,'\0',Size);
1243 + return (pAddress);
1246 +//*****************************************************************************
1247 +// AosMemoryAllocAtomic
1248 +//*****************************************************************************
1249 +VOID * NV_API_CALL AosMemoryAllocAtomic
1251 + IN PAOS_CONTEXT pAosContext,
1252 + IN ULONG Size
1255 + void * pAddress = 0;
1256 + if(!NV_MAY_SLEEP()) {
1257 + pAddress = kmalloc( (size_t)Size, GFP_ATOMIC);
1259 + if(pAddress){
1260 + memset(pAddress,'\0',Size);
1262 + return (pAddress);
1265 +//*****************************************************************************
1266 +// AosMemoryFree
1267 +//*****************************************************************************
1268 +VOID NV_API_CALL AosMemoryFree
1270 + IN PAOS_CONTEXT pAosContext,
1271 + IN VOID * pAddr
1274 + unsigned long vaddr = (unsigned long) pAddr;
1275 + if( vaddr >= VMALLOC_START && vaddr < VMALLOC_END)
1276 + return vfree(pAddr);
1277 + return kfree((const void*) pAddr);
1280 +//*****************************************************************************
1281 +// AosMemoryZero
1282 +//*****************************************************************************
1283 +// Zero a section of memory.
1285 +VOID NV_API_CALL AosMemoryZero
1287 + IN PAOS_CONTEXT pAosContext,
1288 + IN VOID * pData,
1289 + IN ULONG Size
1292 + memset(pData,'\0',Size);
1295 +//*****************************************************************************
1296 +// AosMemoryCopy
1297 +//*****************************************************************************
1298 +// Copy a section of memory to another section of memory.
1300 +VOID NV_API_CALL AosMemoryCopy
1302 + IN PAOS_CONTEXT pAosContext,
1303 + IN VOID * pDestination,
1304 + IN VOID * pSource,
1305 + IN ULONG Size
1308 + memcpy(pDestination,pSource,Size);
1311 +//*****************************************************************************
1312 +// AosMemoryCompare
1313 +//*****************************************************************************
1314 +// Compares one memory area to another based on size.
1316 +BOOL NV_API_CALL AosMemoryCompare
1318 + IN PAOS_CONTEXT pAosContext,
1319 + IN VOID * pSource1,
1320 + IN VOID * pSource2,
1321 + IN ULONG Length
1324 + int retValue = memcmp(pSource1,pSource2,Length);
1325 + // To make it compatible with windows
1326 + return ( (retValue)? 0 : 1);
1330 +//*****************************************************************************
1331 +// AosMemorySet
1332 +//*****************************************************************************
1333 +// Set thememory area with a single value
1335 +VOID NV_API_CALL AosMemorySet
1337 + IN PAOS_CONTEXT pAosContext,
1338 + IN VOID * pDestination,
1339 + IN VOID * pData,
1340 + IN ULONG Length
1343 + memset(pDestination,(int)(LONG_PTR)pData,Length);
1346 +//*****************************************************************************
1347 +// AosAtomicDecrement
1348 +//*****************************************************************************
1349 +// Atomically decrements the value at the specified address and returns the
1350 +// new value.
1352 +LONG NV_API_CALL AosAtomicDecrement
1354 + IN PAOS_CONTEXT pAosContext,
1355 + IN VOID* pAddr
1358 + atomic_dec((atomic_t *) pAddr);
1359 + return atomic_read((atomic_t *) pAddr);
1362 +//*****************************************************************************
1363 +// AosAtomicIncrement
1364 +//*****************************************************************************
1365 +// Atomically increments the value at the specified address and returns the
1366 +// new value.
1368 +LONG NV_API_CALL AosAtomicIncrement
1370 + IN PAOS_CONTEXT pAosContext,
1371 + IN VOID* pAddr
1374 + atomic_inc((atomic_t *) pAddr);
1375 + return atomic_read((atomic_t *)pAddr);
1378 +//*****************************************************************************
1379 +// AosAtomicSet
1380 +//*****************************************************************************
1381 +// Atomically sets the value at the specified address and returns the old
1382 +// value.
1384 +LONG NV_API_CALL AosAtomicSet
1386 + IN PAOS_CONTEXT pAosContext,
1387 + IN VOID* pAddr,
1388 + IN ULONG Value
1391 + signed int oldvalue = atomic_read((atomic_t *) pAddr);
1392 + atomic_set((atomic_t *)pAddr,Value);
1393 + return oldvalue;
1396 +//*****************************************************************************
1397 +// AosGetPhysicalAddr
1398 +//*****************************************************************************
1399 +void* NV_API_CALL AosGetPhysicalAddr
1401 + IN PVOID pLinAddr
1404 + return (void*) virt_to_phys(pLinAddr);
1407 +//*****************************************************************************
1408 +// AosGetPhysicalAddr
1409 +//*****************************************************************************
1410 +void * NV_API_CALL AosGetLinearAddress(IN unsigned long physAddr)
1412 + return (void *) phys_to_virt(physAddr);
1418 +// Defining the NVA_SPINLOCK
1420 +struct NVA_SPINLOCK
1422 + // spinlock variable
1423 + spinlock_t Lock;
1424 + // This is the AOS context for the list.
1425 + PAOS_CONTEXT AosCtx;
1426 + // Set if the lock is acquired.
1427 + ULONG Locked;
1428 + // To save the flags at IRQ state
1429 + unsigned long flags;
1431 +//*****************************************************************************
1432 +// AosSpinLockCreate
1433 +//*****************************************************************************
1434 +// Creates a new spin lock.
1435 +// The spinlock must be freed with AosSpinLockFree.
1437 +unsigned long NV_API_CALL AosSpinLockCreate
1439 + IN PAOS_CONTEXT pAosContext,
1440 + IN PNVA_SPINLOCK* ppSpinLock
1443 + *ppSpinLock =
1444 + (PNVA_SPINLOCK)AosMemoryAlloc(pAosContext, sizeof(struct NVA_SPINLOCK));
1445 + if(!*ppSpinLock)
1447 + printk("Nvsound: Failed to allocate the spinlock! \n");
1448 + *ppSpinLock = 0;
1449 + return NVA_INSUFFICIENT_RESOURCES;
1452 + (*ppSpinLock)->AosCtx = pAosContext;
1453 + (*ppSpinLock)->Locked = 0;
1454 + (*ppSpinLock)->flags = 0;
1455 + spin_lock_init(&(*ppSpinLock)->Lock);
1456 + return NVA_OK;
1459 +//*****************************************************************************
1460 +// AosSpinLockFree
1461 +//*****************************************************************************
1462 +// Releases an allocated spinlock.
1464 +VOID NV_API_CALL AosSpinLockFree
1466 + IN PNVA_SPINLOCK pSpinLock
1469 + AosMemoryFree(pSpinLock->AosCtx, pSpinLock);
1472 +//*****************************************************************************
1473 +// AosSpinLockAcquire
1474 +//*****************************************************************************
1475 +// Acquire the spin lock
1477 +VOID NV_API_CALL AosSpinLockAcquire
1479 + IN PNVA_SPINLOCK pSpinLock
1482 + if(pSpinLock){
1483 + spin_lock(&pSpinLock->Lock);
1484 + pSpinLock->Locked = 1;
1488 +//*****************************************************************************
1489 +// AosSpinLockIsLocked
1490 +//*****************************************************************************
1491 +// This tells us if the locked is currently held.
1492 +BOOL NV_API_CALL AosSpinLockIsLocked
1494 + IN PNVA_SPINLOCK pSpinLock
1497 + return (BOOL)pSpinLock->Locked;
1500 +//*****************************************************************************
1501 +// AosSpinLockRelease
1502 +//*****************************************************************************
1503 +// Release the spin lock.
1505 +VOID NV_API_CALL AosSpinLockRelease
1507 + IN PNVA_SPINLOCK pSpinLock
1510 + if(pSpinLock){
1511 + pSpinLock->Locked = 0;
1512 + spin_unlock(&pSpinLock->Lock);
1516 +//*****************************************************************************
1517 +// AosThreadDelay
1518 +//*****************************************************************************
1519 +// Delay the execution of the current thread by the specified number of
1520 +// milliseconds.
1522 +VOID NV_API_CALL AosThreadDelay
1524 + IN PAOS_CONTEXT pAosContext,
1525 + IN unsigned long Milliseconds
1528 + mdelay(Milliseconds);
1531 +//*****************************************************************************
1532 +// AosDelay
1533 +//*****************************************************************************
1534 +// Stall the executing processor by the specified number of microseconds.
1536 +inline VOID NV_API_CALL AosDelay
1538 + IN PAOS_CONTEXT pAosContext,
1539 + IN unsigned long Microseconds
1542 + // using udelay now - have to look whether any function to stall the processor if neccessary.
1543 + udelay(Microseconds);
1547 +//*****************************************************************************
1548 +// AosPeek8
1549 +//*****************************************************************************
1550 +// Read an 8-bit value from the specified address.
1552 +unsigned char NV_API_CALL AosPeek8
1554 + IN PAOS_CONTEXT pAosContext,
1555 + IN VOID * pAddr
1558 + return (unsigned char)inb((unsigned long)pAddr);
1561 +//*****************************************************************************
1562 +// AosPeek16
1563 +//*****************************************************************************
1564 +// Read a 16-bit value from the specified address.
1566 +unsigned short NV_API_CALL AosPeek16
1568 + IN PAOS_CONTEXT pAosContext,
1569 + IN VOID * pAddr
1572 + return (unsigned short)inw((unsigned long)pAddr);
1575 +//*****************************************************************************
1576 +// AosPeek32
1577 +//*****************************************************************************
1578 +// Read a 32-bit value from the specified address.
1580 +unsigned int NV_API_CALL AosPeek32
1582 + IN PAOS_CONTEXT pAosContext,
1583 + IN VOID * pAddr
1586 + return (unsigned int)inl((unsigned long)pAddr);
1589 +//*****************************************************************************
1590 +// AosPoke8
1591 +//*****************************************************************************
1592 +// Write an 8-bit value to the specified address.
1594 +VOID NV_API_CALL AosPoke8
1596 + IN PAOS_CONTEXT pAosContext,
1597 + IN VOID * pAddr,
1598 + IN unsigned char Value
1601 + outb(Value,(unsigned long)pAddr);
1604 +//*****************************************************************************
1605 +// AosPoke16
1606 +//*****************************************************************************
1607 +// Write a 16-bit value to the specified address.
1609 +VOID NV_API_CALL AosPoke16
1611 + IN PAOS_CONTEXT pAosContext,
1612 + IN VOID * pAddr,
1613 + IN unsigned short Value
1616 + outw(Value,(unsigned long)pAddr);
1619 +//*****************************************************************************
1620 +// AosPoke32
1621 +//*****************************************************************************
1622 +// Write a 32-bit value to the specified address.
1624 +VOID NV_API_CALL AosPoke32
1626 + IN PAOS_CONTEXT pAosContext,
1627 + IN VOID * pAddr,
1628 + IN ULONG Value
1631 + outl(Value,(unsigned long)pAddr);
1634 +//*****************************************************************************
1635 +// AosFpRestore
1636 +//*****************************************************************************
1637 +VOID NV_API_CALL AosFpRestore(IN PAOS_CONTEXT pAosContext)
1641 +//*****************************************************************************
1642 +// AosFpSave
1643 +//*****************************************************************************
1644 +VOID NV_API_CALL AosFpSave(IN PAOS_CONTEXT pAosContext)
1648 +//*****************************************************************************
1649 +// AosInterruptStatePop
1650 +//*****************************************************************************
1651 +VOID NV_API_CALL AosInterruptStatePop(IN PAOS_CONTEXT pAosContext,IN NVA_INTERRUPT_STATE State)
1653 + spin_unlock_irqrestore(&global_spinlock,global_flags);
1654 + global_spinlock = SPIN_LOCK_UNLOCKED;
1657 +//*****************************************************************************
1658 +// AosInterruptStatePush
1659 +//*****************************************************************************
1660 +VOID NV_API_CALL AosInterruptStatePush(IN PAOS_CONTEXT pAosContext,IN NVA_INTERRUPT_STATE* pState)
1662 + spin_lock_irqsave(&global_spinlock,global_flags);
1665 +//*****************************************************************************
1666 +// AosMemoryPhysicalAddressListGet
1667 +//*****************************************************************************
1668 +VOID NV_API_CALL AosMemoryPhysicalAddressListGet
1669 +( IN PAOS_CONTEXT pAosContext,
1670 + IN VOID * pKernelAddress,
1671 + IN ULONG Size,
1672 + IN PNVA_AST* ppPhysicalAddressList,
1673 + IN ULONG* pNumberOfPhysicalAddressListEntries
1676 + PNVA_AST pPhysicalArray, addrArray;
1677 + ULONG prds = 0, arraysize = 0, icount = 0;
1678 + unsigned long phys_addr = 0, virt_addr = 0, isvmalloc = 0;
1681 + ASSERT(pKernelAddress);
1682 + ASSERT(ppPhysicalAddressList);
1683 + ASSERT(pNumberOfPhysicalAddressListEntries);
1685 + *ppPhysicalAddressList = 0;
1686 + *pNumberOfPhysicalAddressListEntries = 0;
1688 + prds = COMPUTE_PAGES_SPANNED(pKernelAddress, Size);
1690 + // Create the list for the array to store the page's physical addr
1691 + arraysize = (sizeof(NVA_AST)* (prds + 1));
1692 + addrArray = (PNVA_AST) AosMemoryAlloc(0,arraysize);
1693 + if(addrArray) {
1694 + AosMemoryZero(0,addrArray,arraysize);
1696 + else {
1697 + printk(KERN_INFO "Nvsound: Unable to allocate the memory prd list- ");
1698 + return;
1701 + // Save the size
1702 + *addrArray = Size;
1703 + addrArray++;
1704 + pPhysicalArray = addrArray;
1706 + //
1707 + // Verify the address is vmalloced one
1708 + //
1709 + virt_addr = (unsigned long)pKernelAddress;
1710 + if( virt_addr >= VMALLOC_START && virt_addr < VMALLOC_END)
1711 + isvmalloc = 1;
1713 + //
1714 + // Obtain the physical address from virtual address.
1715 + //
1716 +#if defined (__i386__)
1717 + if(isvmalloc){
1718 + for(icount = 0; icount < prds ; icount++) {
1719 + phys_addr = nv_get_kern_phys_address(virt_addr);
1720 + if(phys_addr == 0){
1721 + printk(KERN_INFO "Nvsound: Unable to allocate the physical memory- ");
1722 + return;
1724 + *pPhysicalArray = (u32)phys_addr;
1725 + pPhysicalArray++;
1726 + virt_addr += PAGE_SIZE;
1728 + }else
1729 +#endif
1731 + for(icount = 0; icount < prds ; icount++) {
1732 + *pPhysicalArray = (u32) virt_to_phys((char *)pKernelAddress+(icount*PAGE_SIZE));
1733 + pPhysicalArray++;
1734 + }
1737 + *ppPhysicalAddressList = addrArray;
1738 + *pNumberOfPhysicalAddressListEntries = prds;
1739 + return;
1743 +//*****************************************************************************
1744 +// AosMemoryPhysicalAddressListFree
1745 +//*****************************************************************************
1746 +VOID NV_API_CALL AosMemoryPhysicalAddressListFree(IN PAOS_CONTEXT pAosContext,IN PNVA_AST pPhysicalAddressList)
1748 + ULONG uSize;
1749 + PNVA_AST pPhysArray;
1751 + ASSERT(pPhysicalAddressList);
1753 + // find the number of prds first
1754 + if(pPhysicalAddressList){
1755 + //printk(KERN_INFO "Nvsound: Phy Array %x ", (unsigned long)pPhysicalAddressList);
1756 + pPhysArray = (PNVA_AST)(pPhysicalAddressList - 1);
1757 + uSize = *pPhysArray;
1758 + //printk(KERN_INFO "Nvsound: AosMemoryFreePhysical- Size 0x%x VA 0x%x PA 0x%x",uSize,(unsigned long)pKernelAddress,(unsigned long)dmaHandle);
1759 + AosMemoryFree(0,pPhysArray);
1763 +//*****************************************************************************
1764 +// AosMemoryAllocPhysical
1765 +//*****************************************************************************
1766 +VOID NV_API_CALL AosMemoryAllocPhysical
1768 + IN PAOS_CONTEXT pAosContext,
1769 + IN ULONG Size,
1770 + IN NVA_U64 LowAddress,
1771 + IN NVA_U64 HighAddress,
1772 + IN VOID ** ppKernelAddress,
1773 + IN VOID ** ppUserAddress,
1774 + IN PNVA_AST* ppPhysicalAddressList,
1775 + IN PULONG pNumberOfPhysicalAddressListEntries,
1776 + IN MEMORY_CACHING_TYPE CacheType
1779 + struct page *pgend, *pgcount;
1780 + PNVA_AST pPhysicalArray, addrArray;
1781 + void *addr;
1782 + ULONG prds = 0, newSize = 0, icount = 0, arraysize = 0;
1783 + dma_addr_t dmaHandle;
1784 + newSize = ROUND_TO_PAGES(Size);
1786 + ASSERT(ppKernelAddress);
1787 + ASSERT(ppPhysicalAddressList);
1788 + ASSERT(pNumberOfPhysicalAddressListEntries);
1790 + // alloc memory
1791 + addr = pci_alloc_consistent(pAci_device,newSize,&dmaHandle);
1792 + if(addr) {
1793 + prds = COMPUTE_PAGES_SPANNED(addr,newSize);
1796 + // Create the list for the array to store the page's physical addr
1797 + arraysize = (sizeof(NVA_AST)* (prds + 1));
1798 + addrArray = (PNVA_AST) AosMemoryAlloc(0,arraysize);
1799 + if(addrArray) {
1800 + AosMemoryZero(0,addrArray,arraysize);
1802 + else {
1803 + printk(KERN_INFO "Nvsound: Unable to allocate the memory- ");
1804 + pci_free_consistent(pAci_device,newSize ,addr,dmaHandle);
1805 + return;
1807 + // Save the size
1808 + *addrArray = newSize;
1809 + addrArray++;
1810 + pPhysicalArray = addrArray;
1812 + // mark the pages are reserved now - not marking now
1813 + if(CacheType == MmCached) {
1814 + pgend = virt_to_page((u8 *)addr + (newSize-1));
1815 + for( pgcount = virt_to_page(addr); pgcount <= pgend; pgcount++) {
1816 + SetPageReserved(pgcount);
1820 + for(icount = 0; icount < prds ; icount++) {
1821 + *pPhysicalArray = (u32)dmaHandle +(icount*PAGE_SIZE);
1822 + pPhysicalArray++;
1823 + }
1824 + //printk(KERN_INFO "Nvsound: AosMemoryPhysical- Size 0x%x VA 0x%lx PA 0x%lx prdlist 0x%x Prds 0x%x \n",
1825 + // newSize,(unsigned long)addr,(unsigned long)dmaHandle,pPhysicalArray,prds);
1826 + *ppKernelAddress = addr;
1827 + *ppPhysicalAddressList = addrArray;
1828 + *pNumberOfPhysicalAddressListEntries = prds;
1833 +//*****************************************************************************
1834 +// AosVmAllocPhysical
1835 +//*****************************************************************************
1836 +VOID NV_API_CALL AosVmAllocPhysical
1838 + IN ULONG Size,
1839 + IN VOID ** ppKernelAddress,
1840 + IN PNVA_AST* ppPhysicalAddressList,
1841 + IN PULONG pNumberOfPhysicalAddressListEntries
1844 +#if defined (__i386__)
1846 + PNVA_AST pPhysicalArray, addrArray;
1847 + void *addr = 0;
1848 + unsigned long phys_addr = 0, virt_addr = 0;
1849 + ULONG prds = 0, newSize = 0, icount = 0, arraysize = 0, rcount = 0;
1851 + newSize = ROUND_TO_PAGES(Size);
1853 + // alloc memory
1854 + addr = vmalloc_32(newSize);
1855 + virt_addr = (unsigned long) addr;
1856 + if(virt_addr) {
1857 + prds = COMPUTE_PAGES_SPANNED(addr,newSize);
1858 + memset(addr,0,newSize);
1859 + }else{
1860 + printk("Unable to allocate the vmalloc memory \n");
1861 + return;
1864 + // Create the list for the array to store the page's physical addr
1865 + arraysize = (sizeof(NVA_AST)* (prds + 1));
1866 + addrArray = (PNVA_AST) AosMemoryAlloc(0,arraysize);
1867 + if(addrArray) {
1868 + AosMemoryZero(0,addrArray,arraysize);
1870 + else {
1871 + printk(KERN_INFO "Nvsound: Unable to allocate the memory- ");
1872 + AosMemoryFree(0,addr);
1873 + return;
1876 + // Save the size
1877 + *addrArray = newSize;
1878 + addrArray++;
1879 + pPhysicalArray = addrArray;
1881 + for(icount = 0; icount < prds ; icount++) {
1882 + phys_addr = nv_get_kern_phys_address(virt_addr);
1883 + //printk("%lx \n", phys_addr);
1884 + if(phys_addr == 0){
1885 + printk(KERN_INFO "Nvsound: Unable to allocate the physical memory- ");
1886 + goto failed;
1888 + /* lock the page for dma purposes */
1889 + SetPageReserved(NV_GET_PAGE_STRUCT(phys_addr));
1891 + *pPhysicalArray = (u32)phys_addr;
1892 + pPhysicalArray++;
1894 + // This will work only in 32bit version.
1895 + // Need changes for 64bit
1896 + NV_SET_PAGE_ATTRIB_UNCACHED(phys_addr);
1898 + virt_addr += PAGE_SIZE;
1899 + }
1901 + nv_flush_caches();
1903 + //printk(KERN_INFO "Nvsound: AosVmAllocPhysical- Size 0x%x VA 0x%p Prds 0x%x \n",
1904 + // newSize,addr,prds);
1905 + *ppKernelAddress = addr;
1906 + *ppPhysicalAddressList = addrArray;
1907 + *pNumberOfPhysicalAddressListEntries = prds;
1909 + return;
1911 +failed:
1912 + pPhysicalArray = addrArray;
1913 + virt_addr = (unsigned long) addr;
1914 + for(rcount = 0; rcount < icount; rcount++) {
1915 + phys_addr = (unsigned long)*pPhysicalArray;
1916 + ClearPageReserved(NV_GET_PAGE_STRUCT(phys_addr));
1917 + NV_SET_PAGE_ATTRIB_CACHED(phys_addr);
1918 + pPhysicalArray++;
1921 + nv_flush_caches();
1923 + AosMemoryFree(0,addr);
1924 + AosMemoryFree(0,addrArray);
1926 +#else //defined (__x86_64__)
1927 + AosMemoryAllocPhysical(0, Size, 0x00000000, 0xffffffff, ppKernelAddress, 0, ppPhysicalAddressList, pNumberOfPhysicalAddressListEntries,MmCached);
1928 +#endif
1933 +//*****************************************************************************
1934 +// AosVmFreePhysical
1935 +//*****************************************************************************
1936 +VOID NV_API_CALL AosVmFreePhysical
1938 + IN VOID * pKernelAddress,
1939 + IN PNVA_AST pPhysicalAddressList
1942 +#if defined (__i386__)
1944 + ULONG uSize, prds = 0, icount = 0;
1945 + unsigned long phys_addr = 0;
1946 + PNVA_AST pPhysArray, pPhysList;
1949 + // find the number of prds first
1950 + if(pPhysicalAddressList){
1951 + pPhysArray = (PNVA_AST)(pPhysicalAddressList - 1);
1952 + uSize = *pPhysArray;
1953 + pPhysList = pPhysicalAddressList;
1954 + prds = COMPUTE_PAGES_SPANNED(pKernelAddress,uSize);
1956 + for(icount = 0; icount < prds ; icount++) {
1957 + phys_addr = (unsigned long)*pPhysList;
1958 + ClearPageReserved(NV_GET_PAGE_STRUCT(phys_addr));
1959 + NV_SET_PAGE_ATTRIB_CACHED(phys_addr);
1960 + pPhysList++;
1963 + nv_flush_caches();
1965 + AosMemoryFree(0,pKernelAddress);
1966 + AosMemoryFree(0,pPhysArray);
1969 +#else //defined (__x86_64__)
1970 + AosMemoryFreePhysical(0, pKernelAddress, (ULONG32)MmCached, pPhysicalAddressList);
1971 +#endif
1973 +//*****************************************************************************
1974 +// AosMemoryFreePhysical
1975 +//*****************************************************************************
1976 +VOID NV_API_CALL AosMemoryFreePhysical
1978 + IN PAOS_CONTEXT pAosContext,
1979 + IN VOID * pKernelAddress,
1980 + IN ULONG CacheValue,
1981 + IN PNVA_AST pPhysicalAddressList
1984 + ULONG uSize;
1985 + dma_addr_t dmaHandle;
1986 + PNVA_AST pPhysArray;
1987 + struct page *pgend, *pgcount;
1988 + MEMORY_CACHING_TYPE CacheType;
1990 + ASSERT(pKernelAddress);
1991 + ASSERT(pPhysicalAddressList);
1993 + // find the number of prds first
1994 + if(pPhysicalAddressList){
1995 + //printk(KERN_INFO "Nvsound: Phy Array %x ", (unsigned long)pPhysicalAddressList);
1996 + pPhysArray = (PNVA_AST)(pPhysicalAddressList - 1);
1997 + uSize = *pPhysArray;
1998 + dmaHandle = *pPhysicalAddressList;
1999 + //printk(KERN_INFO "Nvsound: AosMemoryFreePhysical- Size 0x%x VA 0x%x PA 0x%x",uSize,(unsigned long)pKernelAddress,(unsigned long)dmaHandle);
2001 + // unmark the pages are reserved now
2002 + if(CacheValue) {
2003 + CacheType = (MEMORY_CACHING_TYPE)CacheValue ;
2004 + if(CacheType == MmCached){
2005 + pgend = virt_to_page((u8 *)pKernelAddress + (uSize-1));
2006 + for( pgcount = virt_to_page(pKernelAddress); pgcount <= pgend; pgcount++) {
2007 + ClearPageReserved(pgcount);
2011 + pci_free_consistent(pAci_device,uSize ,pKernelAddress,dmaHandle);
2012 + AosMemoryFree(0,pPhysArray);
2017 +//*****************************************************************************
2018 +// AosDelayThread
2019 +//*****************************************************************************
2020 +VOID NV_API_CALL AosDelayThread(IN PAOS_CONTEXT pAosContext,IN unsigned long Microseconds)
2025 +//*****************************************************************************
2026 +// AosDebugPrint
2027 +//*****************************************************************************
2028 +VOID NV_API_CALL AosDebugPrint
2030 + IN char * Format, ...
2033 + //
2034 + // Write the string to a buffer.
2035 + //
2036 + char buffer[256];
2037 + va_list vaList;
2038 + ULONG size = 0;
2040 + AosMemoryZero(NULL,&buffer,256);
2041 + va_start(vaList, Format);
2042 + vsnprintf(buffer, sizeof(buffer), Format, vaList);
2043 + va_end(vaList);
2044 + size = strlen(buffer);
2045 + printk(KERN_INFO "%s ",buffer);
2046 + return;
2049 +//*****************************************************************************
2050 +// AosSprintf
2051 +//*****************************************************************************
2052 +int NV_API_CALL AosSprintf
2054 + IN char * string,
2055 + IN const char * format,
2056 + ...
2059 + int chars_written = 0;
2060 + va_list arglist;
2062 + va_start(arglist, format);
2063 + chars_written = sprintf(string, format, arglist);
2064 + va_end(arglist);
2066 + return chars_written;
2069 +//*****************************************************************************
2070 +// AosStrcpy
2071 +//*****************************************************************************
2072 +char* NV_API_CALL AosStrcpy(char *dest, const char *src)
2074 + return strcpy(dest,src);
2077 +//*****************************************************************************
2078 +// AosStrlen
2079 +//*****************************************************************************
2080 +int NV_API_CALL AosStrlen(char *src)
2082 + return (int)strlen((const char *)src);
2085 +//*****************************************************************************
2086 +// AosStrcat
2087 +//*****************************************************************************
2088 +char* NV_API_CALL AosStrcat(char *dest, const char *src)
2090 + return strcat(dest,src);
2093 +//*****************************************************************************
2094 +// AosStrcmp
2095 +//*****************************************************************************
2096 +int NV_API_CALL AosStrcmp(const char *s1, const char *s2)
2098 + return strcmp(s1,s2);
2101 +//*****************************************************************************
2102 +// AosMemCpyFromUsr
2103 +//*****************************************************************************
2104 +int NV_API_CALL AosMemCpyFromUsr(void *dest,const void* src,ULONG length)
2106 + return copy_from_user(dest, src, length);
2109 +//*****************************************************************************
2110 +// AosMemCpyToUsr
2111 +//*****************************************************************************
2112 +int NV_API_CALL AosMemCpyToUsr(void *dest,const void* src,ULONG length)
2114 + return copy_to_user(dest, src, length);
2117 +//*****************************************************************************
2118 +// AosSetPciDevice
2119 +//*****************************************************************************
2120 +// Function to set the pci_dev
2121 +VOID NV_API_CALL AosSetPciDevice(VOID * pAciDev,VOID * pApuDev)
2123 + pAci_device = (struct pci_dev *)pAciDev;
2124 + pApu_device = (struct pci_dev *)pApuDev;
2125 + //printk(KERN_INFO "Nvsound: Aci_device %p Apu_device %p \n",pAci_device,pApu_device);
2128 +//*****************************************************************************
2129 +// AosClearPciDevice
2130 +//*****************************************************************************
2131 +// Function to reset the pci_dev
2132 +VOID NV_API_CALL AosResetPciDevice()
2134 + pAci_device = 0;
2135 + pApu_device = 0;
2138 +//*****************************************************************************
2139 +// AosReadPciConfig
2140 +//*****************************************************************************
2141 +// Function to read the data from pci-config space
2142 +VOID NV_API_CALL AosReadPciConfig
2144 + IN VOID * pDevice, IN ULONG *pValue,
2145 + IN ULONG uRegIndex, IN ULONG uLength
2148 + // set the pci_dev first
2149 + struct pci_dev * pdevice = (struct pci_dev *) pDevice;
2151 + ASSERT(pDevice);
2153 + switch(uLength){
2154 + case (sizeof(DWORD)):
2155 + pci_read_config_dword(pdevice,uRegIndex,(u32 *)pValue);
2156 + break;
2157 + default:
2158 + *pValue = 0;
2162 +//*****************************************************************************
2163 +// AosWritePciConfig
2164 +//*****************************************************************************
2165 +// Function to write the data to pci-config space
2166 +VOID NV_API_CALL AosWritePciConfig
2168 + IN VOID * pDevice,IN ULONG uValue,
2169 + IN ULONG uRegIndex, IN ULONG uLength
2172 + struct pci_dev * pdevice = (struct pci_dev *) pDevice;
2174 + ASSERT(pDevice);
2176 + // set the pci_dev first
2177 + switch(uLength){
2178 + case (sizeof(DWORD)):
2179 + pci_write_config_dword(pdevice,uRegIndex,uValue);
2180 + break;
2181 + default:
2182 + uValue = 0;
2187 +//*****************************************************************************
2188 +// AosSetApuResources
2189 +//*****************************************************************************
2190 +// Function to set the APU RESOURCES
2191 +VOID NV_API_CALL AosSetApuResources(IN DEVICE_RESOURCES* device)
2193 + AosResetApuResources();
2194 + apu_res.uPhyAddr = device->uPhyAddr;
2195 + apu_res.uLength = device->uLength;
2196 + apu_res.uIrq = device->uIrq;
2199 +//*****************************************************************************
2200 +// AosResetApuResources
2201 +//*****************************************************************************
2202 +// Function to reset the APU RESOURCES
2203 +VOID NV_API_CALL AosResetApuResources(IN VOID)
2205 + apu_res.uPhyAddr = 0;
2206 + apu_res.uLength = 0;
2207 + apu_res.uIrq = 0;
2210 +//*****************************************************************************
2211 +// AosGetApuResources
2212 +//*****************************************************************************
2213 +// Function to get the APU RESOURCES
2214 +VOID NV_API_CALL AosGetApuResources(IN DEVICE_RESOURCES* device)
2216 + device->uPhyAddr = apu_res.uPhyAddr;
2217 + device->uLength = apu_res.uLength ;
2218 + device->uIrq = apu_res.uIrq;
2221 +//*****************************************************************************
2222 +// AosMapLinearAddress
2223 +//*****************************************************************************
2224 +// Function to map the physical to linear address
2225 +unsigned long NV_API_CALL AosMapLinearAddress(VOID *pPhys, ULONG uSize, VOID**ppLinear)
2227 + *ppLinear = ioremap((unsigned long)pPhys, (ULONG) uSize);
2228 + ApuLinearAddress = (VOID *)*ppLinear;
2229 + return (*ppLinear)?NVA_OK:NVA_ERR;
2232 +//*****************************************************************************
2233 +// AosUnmapLinearAddress
2234 +//*****************************************************************************
2235 +// Unmap the linear address
2236 +VOID NV_API_CALL AosUnmapLinearAddress(VOID *pLinear)
2238 + if(pLinear)
2239 + iounmap(pLinear);
2240 + ApuLinearAddress = 0;
2244 +//****************************************
2245 +// AosGetLinearAddress
2246 +//*****************************************
2247 +VOID * NV_API_CALL AosGetLinearBase(VOID)
2249 + return ApuLinearAddress;
2252 +//****************************************
2253 +// AosSetVapu
2254 +//*****************************************
2255 +VOID NV_API_CALL AosSetVapu(unsigned int value)
2257 + setvapu = value;
2260 +//****************************************
2261 +// AosTimerCreate
2262 +//*****************************************
2263 +unsigned long NV_API_CALL AosTimerCreate(IN PAOS_CONTEXT pAosContext,IN VOID * pContext,
2264 + IN PAOS_TIMER_CALLBACK pCallback,IN PNVA_TIMER* ppTimer)
2266 + struct timer_list *new_timer = (struct timer_list *)AosMemoryAlloc(pAosContext,sizeof(struct timer_list));
2267 + *ppTimer =
2268 + (PNVA_TIMER)AosMemoryAlloc(pAosContext, sizeof(NVA_TIMER));
2269 + if(!*ppTimer)
2271 + printk("Nvsound: Failed to allocate the timer! \n");
2272 + *ppTimer = 0;
2273 + return NVA_INSUFFICIENT_RESOURCES;
2276 + init_timer(new_timer);
2278 + new_timer->function = (VOID *)pCallback;
2279 + new_timer->data = (unsigned long)pContext;
2280 + (*ppTimer)->AosCtx = pAosContext;
2281 + (*ppTimer)->Timer = new_timer;
2282 + (*ppTimer)->Last_Time = 0;
2284 + return NVA_OK;
2287 +//****************************************
2288 +// AosTimerFree
2289 +//*****************************************
2290 +VOID NV_API_CALL AosTimerFree(IN PNVA_TIMER pTimer)
2292 + del_timer(pTimer->Timer);
2293 + AosMemoryFree(pTimer->AosCtx, pTimer->Timer);
2294 + AosMemoryFree(pTimer->AosCtx, pTimer);
2297 +//****************************************
2298 +// AosTimerSet
2299 +//*****************************************
2300 +BOOL NV_API_CALL AosTimerSet(IN PNVA_TIMER pTimer,IN unsigned long DueTimeInMilliseconds,
2301 + IN unsigned long PeriodicTimeInMilliseconds,IN BOOL ResetTimer)
2304 + pTimer->Timer->expires = jiffies + ((DueTimeInMilliseconds * HZ) / 1000);
2305 + if(!ResetTimer) {
2306 + if(pTimer->Timer->expires > pTimer->Last_Time) {
2307 + pTimer->Last_Time = pTimer->Timer->expires;
2308 + add_timer(pTimer->Timer);
2309 + return TRUE;
2311 + }else { // reset an existing timer
2312 + if(pTimer->Timer->expires > pTimer->Last_Time) {
2313 + pTimer->Last_Time = pTimer->Timer->expires;
2314 + mod_timer(pTimer->Timer,pTimer->Timer->expires);
2315 + return TRUE;
2318 + return FALSE;
2322 +#ifdef __cplusplus
2324 +#endif
2326 +#undef ASSERT
2327 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvalinux.h NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvalinux.h
2328 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvalinux.h 2005-10-21 20:59:44.000000000 -0500
2329 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvalinux.h 2008-08-14 10:13:48.000000000 -0500
2330 @@ -43,7 +43,6 @@
2331 typedef long LONG_PTR, *PLONG_PTR, INT_PTR, *PINT_PTR;
2332 typedef unsigned long ULONG_PTR, *PULONG_PTR, UINT_PTR, *PUINT_PTR;
2333 #define __int3264 __int32
2334 - typedef unsigned int uintptr_t;
2336 #else
2337 typedef long long int INT_PTR, *PINT_PTR;
2338 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvalinux.h.orig NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvalinux.h.orig
2339 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvalinux.h.orig 1969-12-31 18:00:00.000000000 -0600
2340 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvalinux.h.orig 2005-10-21 20:59:44.000000000 -0500
2341 @@ -0,0 +1,335 @@
2342 +/* _NVIDIA_COPYRIGHT_BEGIN_
2344 + * Copyright 2003-2004 by NVIDIA Corporation. All rights reserved. All
2345 + * information contained herein is proprietary and confidential to NVIDIA
2346 + * Corporation. Any use, reproduction, or disclosure without the written
2347 + * permission of NVIDIA Corporation is prohibited.
2349 + * _NVIDIA_COPYRIGHT_END_
2350 + */
2353 +* nvalinux.h
2355 +* Header file for defining our own function call to call kernel functions
2359 +#if !defined __NVALINUX_H_
2360 +#define __NVALINUX_H_
2362 +#if defined __cplusplus
2363 +extern "C" {
2364 +#endif
2366 +#if !defined IN
2367 +#define IN
2368 +#endif
2370 +#if !defined OUT
2371 +#define OUT
2372 +#endif
2374 +#if !defined __int64
2375 +#define __int64 long long int
2376 +#endif
2378 +typedef __int64 LONGLONG;
2380 +#if defined (__i386__)
2381 + /* need to specify INT_PTR as long as we care about 32bits only -
2382 + otherwise it will cause some overloading errors
2383 + */
2384 + typedef long LONG_PTR, *PLONG_PTR, INT_PTR, *PINT_PTR;
2385 + typedef unsigned long ULONG_PTR, *PULONG_PTR, UINT_PTR, *PUINT_PTR;
2386 + #define __int3264 __int32
2387 + typedef unsigned int uintptr_t;
2389 +#else
2390 + typedef long long int INT_PTR, *PINT_PTR;
2391 + typedef unsigned long long int UINT_PTR, *PUINT_PTR;
2392 + typedef __int64 LONG_PTR, *PLONG_PTR;
2393 + typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
2394 + #define __int3264 __int64
2395 + typedef unsigned __int64 uintptr_t;
2396 +#endif
2398 +#if !defined PCHAR
2399 +#define PCHAR char*
2400 +#endif
2402 +#if !defined NVA_OK
2403 +#define NVA_OK 0
2404 +#endif
2406 +#if !defined VOID
2407 +#define VOID void
2408 +#endif
2410 +// make sure the arguments are expected in stack instead of registers
2411 +#if !defined(NV_API_CALL)
2412 +#if defined(__i386__)
2413 +#define NV_API_CALL __attribute__((regparm(0)))
2414 +#else
2415 +#define NV_API_CALL
2416 +#endif
2417 +#endif
2419 +struct AOS_CONTEXT
2421 + unsigned long uFlags;
2423 +typedef struct AOS_CONTEXT *PAOS_CONTEXT;
2425 +typedef struct _DEVICE_RESOURCES
2427 + unsigned long uPhyAddr;
2428 + unsigned int iobase0;
2429 + unsigned int iobase1;
2430 + unsigned int uLength;
2431 + unsigned int uIrq;
2432 +}DEVICE_RESOURCES;
2434 +typedef struct _NEW_MEM_HEADER
2436 + VOID * pVirtualAddr;
2437 + VOID * pPhysArray;
2438 +}NEW_MEM_HEADER;
2440 +#define NVA_ERR 900
2441 +#define NVA_NO_INTERFACE 901
2442 +#define NVA_NOT_IMPLEMENTED 902
2443 +#define NVA_INVALID_PARAMETER 903
2444 +#define NVA_INSUFFICIENT_RESOURCES 904
2445 +#define NVA_INVALID_DEVICE_STATE 905
2447 +#if !defined TRUE
2448 +#define TRUE 1
2449 +#endif
2451 +#if !defined FALSE
2452 +#define FALSE 0
2453 +#endif
2455 +typedef signed int LONG32, *PLONG32;
2456 +typedef unsigned int ULONG32, *PULONG32;
2457 +typedef unsigned int DWORD32, *PDWORD32;
2459 +typedef unsigned int DWORD;
2460 +typedef unsigned int ULONG;
2461 +typedef int LONG;
2462 +typedef int BOOL;
2463 +typedef unsigned char BOOLEAN;
2464 +typedef unsigned char BYTE;
2465 +typedef float FLOAT;
2466 +typedef LONGLONG REFERENCE_TIME;
2467 +typedef unsigned short WORD;
2470 +typedef DWORD *PDWORD;
2471 +typedef BOOL *LPBOOL, *PBOOL;
2472 +typedef BYTE *PBYTE, *LPBYTE;
2473 +typedef VOID *PVOID, *LPVOID;
2474 +typedef ULONG *PULONG;
2476 +typedef __int64 LONG64, *PLONG64;
2477 +typedef unsigned __int64 ULONG64, *PULONG64;
2478 +typedef unsigned __int64 DWORD64, *PDWORD64;
2481 +typedef ULONG_PTR NVA_AST;
2482 +typedef NVA_AST *PNVA_AST;
2485 +// This is the timer callback declaration.
2487 +typedef VOID (*PAOS_TIMER_CALLBACK)
2489 + IN VOID* pContext
2492 +typedef struct _NVA_TIMER_
2494 + PAOS_CONTEXT AosCtx;
2496 + //
2497 + // The timer.
2498 + //
2499 + struct timer_list *Timer;
2501 + //
2502 + // Last time
2503 + //
2504 + unsigned long Last_Time;
2506 +}NVA_TIMER;
2507 +typedef NVA_TIMER *PNVA_TIMER;
2510 +// "void": enumerated or multiple fields
2512 +typedef struct
2514 + unsigned long Low;
2515 + unsigned long High;
2517 +} NVA_V64, *PNVA_V64;
2520 +// 0 to 18446744073709551615
2522 +typedef unsigned __int64 NVA_U64;
2523 +typedef NVA_U64* PNVA_U64;
2526 +// 2^-63 to 2^63-1
2528 +typedef __int64 NVA_S64;
2529 +typedef NVA_S64* PNVA_S64;
2532 +// 64-bit void pointer
2534 +typedef struct
2536 + unsigned long Low;
2537 + unsigned long High;
2539 +} NVA_P64, *PNVA_P64;
2541 +struct NVA_SPINLOCK;
2542 +typedef struct NVA_SPINLOCK* PNVA_SPINLOCK;
2544 +typedef unsigned long NVA_INTERRUPT_STATE;
2545 +typedef NVA_INTERRUPT_STATE* PNVA_INTERRUPT_STATE;
2547 +#define MAX_PATH 260
2549 +#if defined __cplusplus
2550 +void* operator new (IN size_t iSize);
2551 +void operator delete (IN PVOID pAddr);
2552 +#endif
2554 +typedef enum _MEMORY_CACHING_TYPE {
2555 + MmNonCached,
2556 + MmCached,
2557 + MmWriteCombined
2558 +} MEMORY_CACHING_TYPE;
2560 +#ifdef DEFINE_GLOBAL_VARS
2561 +struct AOS_CONTEXT AosContext;
2562 +#else
2563 +extern struct AOS_CONTEXT AosContext;
2564 +#endif
2566 +#if !defined PAGE_ALIGN
2567 +#define PAGE_ALIGN(Va) ((PVOID)((ULONG_PTR)(Va) & ~(PAGE_SIZE - 1)))
2568 +#endif
2570 +#if !defined ROUND_TO_PAGES
2571 +#define ROUND_TO_PAGES(Size) (((ULONG_PTR)(Size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
2572 +#endif
2574 +#if !defined COMPUTE_PAGES_SPANNED
2575 +#define COMPUTE_PAGES_SPANNED(Va, Size) \
2576 + ((ULONG)((((ULONG_PTR)(Va) & (PAGE_SIZE -1)) + (Size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
2577 +#endif
2580 +VOID* NV_API_CALL AosMemoryAlloc(IN PAOS_CONTEXT pAosContext,IN ULONG Size);
2582 +VOID* NV_API_CALL AosMemoryAllocVM(IN PAOS_CONTEXT pAosContext,IN ULONG Size);
2583 +VOID* NV_API_CALL AosMemoryAllocAtomic(IN PAOS_CONTEXT pAosContext,IN ULONG Size);
2584 +VOID NV_API_CALL AosMemoryFree (IN PAOS_CONTEXT pAosContext,IN VOID * pAddr);
2585 +VOID NV_API_CALL AosMemoryZero(IN PAOS_CONTEXT pAosContext,IN VOID * pData,IN ULONG Size);
2586 +VOID NV_API_CALL AosMemoryCopy(IN PAOS_CONTEXT pAosContext,IN VOID * pDestination, IN VOID * pSource,IN ULONG Size);
2587 +BOOL NV_API_CALL AosMemoryCompare(IN PAOS_CONTEXT pAosContext,IN VOID * pSource1,IN VOID * pSource2,IN ULONG Length);
2588 +VOID NV_API_CALL AosMemorySet(IN PAOS_CONTEXT pAosContext,IN VOID * pDestination,IN VOID * pData,IN ULONG Length);
2589 +VOID* NV_API_CALL AosGetPhysicalAddr(IN PVOID pLinAddr);
2590 +VOID* NV_API_CALL AosGetLinearAddress(IN unsigned long PhysAddr);
2592 +LONG NV_API_CALL AosAtomicDecrement(IN PAOS_CONTEXT pAosContext,IN VOID *pAddr);
2593 +LONG NV_API_CALL AosAtomicIncrement(IN PAOS_CONTEXT pAosContext,IN VOID *pAddr);
2594 +LONG NV_API_CALL AosAtomicSet(IN PAOS_CONTEXT pAosContext,IN VOID *pAddr,IN ULONG Value);
2596 +unsigned long NV_API_CALL AosSpinLockCreate(IN PAOS_CONTEXT pAosContext,IN PNVA_SPINLOCK* ppSpinLock);
2597 +VOID NV_API_CALL AosSpinLockFree(IN PNVA_SPINLOCK pSpinLock);
2598 +VOID NV_API_CALL AosSpinLockAcquire(IN PNVA_SPINLOCK pSpinLock);
2599 +BOOL NV_API_CALL AosSpinLockIsLocked(IN PNVA_SPINLOCK pSpinLock);
2600 +VOID NV_API_CALL AosSpinLockRelease(IN PNVA_SPINLOCK pSpinLock);
2601 +VOID NV_API_CALL AosDelay(IN PAOS_CONTEXT pAosContext,IN unsigned long Microseconds);
2602 +VOID NV_API_CALL AosDelayThread(IN PAOS_CONTEXT pAosContext,IN unsigned long Microseconds);
2604 +VOID NV_API_CALL AosFpRestore(IN PAOS_CONTEXT pAosContext);
2605 +VOID NV_API_CALL AosFpSave(IN PAOS_CONTEXT pAosContext);
2606 +VOID NV_API_CALL AosInterruptStatePop(IN PAOS_CONTEXT pAosContext,IN NVA_INTERRUPT_STATE State);
2607 +VOID NV_API_CALL AosInterruptStatePush(IN PAOS_CONTEXT pAosContext,IN NVA_INTERRUPT_STATE* pState);
2608 +VOID NV_API_CALL AosMemoryPhysicalAddressListGet( IN PAOS_CONTEXT pAosContext,IN VOID * pKernelAddress,IN ULONG Size,
2609 + IN PNVA_AST* ppPhysicalAddressList,IN ULONG * pNumberOfPhysicalAddressListEntries);
2610 +VOID NV_API_CALL AosMemoryPhysicalAddressListFree(IN PAOS_CONTEXT pAosContext,IN PNVA_AST pPhysicalAddressList);
2611 +VOID NV_API_CALL AosMemoryAllocPhysical(IN PAOS_CONTEXT pAosContext,IN ULONG Size,IN NVA_U64 LowAddress,IN NVA_U64 HighAddress,
2612 + IN VOID ** ppKernelAddress,IN VOID ** ppUserAddress,IN PNVA_AST* ppPhysicalAddressList,
2613 + IN PULONG pNumberOfPhysicalAddressListEntries,IN MEMORY_CACHING_TYPE CacheType);
2614 +VOID NV_API_CALL AosMemoryFreePhysical(IN PAOS_CONTEXT pAosContext,IN VOID * pKernelAddress,
2615 + IN ULONG CacheType,IN PNVA_AST pPhysicalAddressList);
2616 +VOID NV_API_CALL AosVmAllocPhysical(IN ULONG Size, IN VOID ** ppKernelAddress, IN PNVA_AST* ppPhysicalAddressList,
2617 + IN PULONG pNumberOfPhysicalAddressListEntries);
2618 +VOID NV_API_CALL AosVmFreePhysical(IN VOID * pKernelAddress, IN PNVA_AST pPhysicalAddressList);
2621 +unsigned char NV_API_CALL AosPeek8(IN PAOS_CONTEXT pAosContext,IN VOID * pAddr);
2622 +unsigned short NV_API_CALL AosPeek16(IN PAOS_CONTEXT pAosContext,IN VOID * pAddr);
2623 +unsigned int NV_API_CALL AosPeek32(IN PAOS_CONTEXT pAosContext,IN VOID * pAddr);
2625 +VOID NV_API_CALL AosPoke8(IN PAOS_CONTEXT pAosContext,IN VOID * pAddr,IN unsigned char Value);
2626 +VOID NV_API_CALL AosPoke16(IN PAOS_CONTEXT pAosContext,IN VOID * pAddr,IN unsigned short Value);
2627 +VOID NV_API_CALL AosPoke32(IN PAOS_CONTEXT pAosContext,IN VOID * pAddr,IN ULONG Value);
2629 +VOID NV_API_CALL AosReadPciConfig(IN VOID * pDevice,IN ULONG *pValue, IN ULONG uRegIndex, IN ULONG uLength);
2630 +VOID NV_API_CALL AosWritePciConfig(IN VOID * pDevice,IN ULONG Value, IN ULONG uRegIndex, IN ULONG uLength);
2631 +VOID NV_API_CALL AosSetPciDevice(IN VOID * pAciDev,IN VOID * pApuDev);
2632 +VOID NV_API_CALL AosResetPciDevice(IN VOID);
2634 +VOID NV_API_CALL AosSetApuResources(IN DEVICE_RESOURCES* device);
2635 +VOID NV_API_CALL AosGetApuResources(IN DEVICE_RESOURCES* device);
2636 +VOID NV_API_CALL AosResetApuResources(IN VOID);
2638 +unsigned long NV_API_CALL AosMapLinearAddress(VOID *pPhys, ULONG uSize, VOID**ppLinear);
2639 +VOID NV_API_CALL AosUnmapLinearAddress(VOID *pLinear);
2641 +VOID NV_API_CALL AosDebugPrint(IN char* Format, ...);
2642 +int NV_API_CALL AosSprintf(IN char *string,IN const char *format, ...);
2644 +/****************************************
2645 +* AOS TIMER ROUTINES
2646 +*****************************************/
2647 +unsigned long NV_API_CALL AosTimerCreate(IN PAOS_CONTEXT pAosContext,IN VOID * pContext,IN PAOS_TIMER_CALLBACK pCallback,IN PNVA_TIMER* ppTimer);
2648 +VOID NV_API_CALL AosTimerFree(IN PNVA_TIMER pTimer);
2649 +BOOL NV_API_CALL AosTimerSet(IN PNVA_TIMER pTimer,IN unsigned long DueTimeInMilliseconds,
2650 + IN unsigned long PeriodicTimeInMilliseconds,IN BOOL ResetTimer);
2652 +///////////////////////////////////
2653 +// Fpu Save & Restore function
2654 +///////////////////////////////////
2655 +VOID NV_API_CALL AosFpuSave(int*);
2656 +VOID NV_API_CALL AosFpuRestore(int);
2657 +VOID* NV_API_CALL AosGetLinearBase(VOID);
2658 +VOID NV_API_CALL AosSetVapu(unsigned int value);
2660 +/////////////////////////////////////////
2661 +// String functions
2662 +/////////////////////////////////////////
2663 +char* NV_API_CALL AosStrcpy(char *dest, const char *src);
2664 +int NV_API_CALL AosStrlen(char *src);
2665 +char* NV_API_CALL AosStrcat(char *dest, const char *src);
2666 +int NV_API_CALL AosStrcmp(const char *s1, const char *s2);
2667 +int NV_API_CALL AosMemCpyFromUsr(void *dest,const void* src,ULONG length);
2668 +int NV_API_CALL AosMemCpyToUsr(void *dest,const void* src,ULONG length);
2670 +#ifdef __cplusplus
2672 +#endif
2674 +#endif
2677 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvavm.h NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvavm.h
2678 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvavm.h 2005-10-21 20:59:44.000000000 -0500
2679 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvavm.h 2008-08-14 10:13:48.000000000 -0500
2680 @@ -202,18 +202,18 @@
2681 * 2.4 kernels, as it's possible some others may be missing this fix and
2682 * we'd prefer to be a little slower flushing caches than hanging the
2683 * system. 2.6 kernels split the flushing out to a seperate call,
2684 - * global_flush_tlb(), so we rely on that.
2685 + * cpa_flush_all(), so we rely on that.
2687 static void nv_flush_caches(void)
2689 -#if defined(KERNEL_2_4)
2690 +/* #if defined(KERNEL_2_4)
2691 #ifdef CONFIG_SMP
2692 smp_call_function(cache_flush, NULL, 1, 1);
2693 #endif
2694 cache_flush(NULL);
2695 #else
2696 - global_flush_tlb();
2697 -#endif
2698 + cpa_flush_all();
2699 +#endif */
2702 static inline int nv_calc_order(unsigned int size)
2703 @@ -231,12 +231,12 @@
2704 static inline void NV_SET_PAGE_ATTRIB_UNCACHED(unsigned long physaddr)
2706 struct page *page = virt_to_page(__va(physaddr));
2707 - change_page_attr(page, 1, PAGE_KERNEL_NOCACHE);
2708 + set_pages_uc(page, 1);
2710 static inline void NV_SET_PAGE_ATTRIB_CACHED(unsigned long physaddr)
2712 struct page *page = virt_to_page(__va(physaddr));
2713 - change_page_attr(page, 1, PAGE_KERNEL);
2714 + set_pages_wb(page, 1);
2716 #else
2717 #define NV_SET_PAGE_ATTRIB_UNCACHED(page_list)
2718 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvavm.h.orig NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvavm.h.orig
2719 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvavm.h.orig 1969-12-31 18:00:00.000000000 -0600
2720 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvavm.h.orig 2005-10-21 20:59:44.000000000 -0500
2721 @@ -0,0 +1,247 @@
2722 +/*
2724 + * Copyright 2003-2004 by NVIDIA Corporation. All rights reserved. All
2725 + * information contained herein is proprietary and confidential to NVIDIA
2726 + * Corporation. Any use, reproduction, or disclosure without the written
2727 + * permission of NVIDIA Corporation is prohibited.
2728 + *
2729 + */
2732 +* nvavm.h
2734 +* Definitions needed for the vm allocations
2738 +#ifndef _NVA_VM_H_
2739 +#define _NVA_VM_H_
2741 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
2742 +# error This driver does not support pre-2.4 kernels!
2743 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
2744 +# define KERNEL_2_4
2745 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
2746 +# error This driver does not support 2.5 kernels!
2747 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 7, 0)
2748 +# define KERNEL_2_6
2749 +#else
2750 +# error This driver does not support development kernels!
2751 +#endif
2753 +#if defined (__i386__)
2754 +#if defined (CONFIG_SMP) && !defined (__SMP__)
2755 +#define __SMP__
2756 +#endif
2758 +#ifndef wbinvd
2759 +#define wbinvd() __asm__ __volatile__("wbinvd" ::: "memory");
2760 +#endif
2761 +#endif /* defined(NVCPU_X86) */
2763 +#ifdef EXPORT_NO_SYMBOLS
2764 +/* don't clutter the kernel namespace with our symbols */
2765 +EXPORT_NO_SYMBOLS;
2766 +#endif
2768 +#define CACHE_FLUSH() asm volatile("wbinvd":::"memory")
2769 +#define WRITE_COMBINE_FLUSH() asm volatile("sfence":::"memory")
2771 +/* vmalloc_32 has to allocate memory under the 4GB mark suitable for
2772 + * DMA use with the hardware. This has to be done differently for
2773 + * different platforms and kernel versions.
2774 + */
2775 +#define NV_GET_FREE_PAGES(ptr, order) \
2776 + { \
2777 + (ptr) = __get_free_pages(NV_GFP_DMA32, order); \
2780 +#define NV_FREE_PAGES(ptr, order) \
2781 + { \
2782 + free_pages(ptr, order); \
2785 +#define NV_GET_PAGE_STRUCT(phys_page) virt_to_page(__va(phys_page))
2786 +#define NV_VMA_PGOFF(vma) ((vma)->vm_pgoff)
2787 +#define NV_VMA_SIZE(vma) ((vma)->vm_end - (vma)->vm_start)
2788 +#define NV_VMA_PRIVATE(vma) ((vma)->vm_private_data)
2791 +// Needed definitions
2793 +#define NV_PGD_OFFSET(address, kernel, mm) \
2794 + ({ \
2795 + pgd_t *__pgd; \
2796 + if (!kernel) \
2797 + __pgd = pgd_offset(mm, address); \
2798 + else \
2799 + __pgd = pgd_offset_k(address); \
2800 + __pgd; \
2801 + })
2803 +#define NV_PGD_PRESENT(pgd) \
2804 + ({ \
2805 + if ((pgd != NULL) && \
2806 + (pgd_bad(*pgd) || pgd_none(*pgd))) \
2807 + /* static */ pgd = NULL; \
2808 + pgd != NULL; \
2809 + })
2811 +#if defined(pmd_offset_map)
2812 +#define NV_PMD_OFFSET(address, pgd) \
2813 + ({ \
2814 + pmd_t *__pmd; \
2815 + __pmd = pmd_offset_map(pgd, address); \
2816 + })
2817 +#define NV_PMD_UNMAP(pmd) pmd_unmap(pmd);
2818 +#else
2819 +#if defined(PUD_SHIFT) /* 4-level pgtable */
2820 +#define NV_PMD_OFFSET(address, pgd) \
2821 + ({ \
2822 + pmd_t *__pmd = NULL; \
2823 + pud_t *__pud; \
2824 + __pud = pud_offset(pgd, address); \
2825 + if ((__pud != NULL) && \
2826 + !(pud_bad(*__pud) || pud_none(*__pud))) \
2827 + __pmd = pmd_offset(__pud, address); \
2828 + __pmd; \
2829 + })
2830 +#else /* 3-level pgtable */
2831 +#define NV_PMD_OFFSET(address, pgd) \
2832 + ({ \
2833 + pmd_t *__pmd; \
2834 + __pmd = pmd_offset(pgd, address); \
2835 + })
2836 +#endif
2837 +#define NV_PMD_UNMAP(pmd)
2838 +#endif
2840 +#define NV_PMD_PRESENT(pmd) \
2841 + ({ \
2842 + if ((pmd != NULL) && \
2843 + (pmd_bad(*pmd) || pmd_none(*pmd))) \
2844 + { \
2845 + NV_PMD_UNMAP(pmd); \
2846 + pmd = NULL; /* mark invalid */ \
2847 + } \
2848 + pmd != NULL; \
2849 + })
2851 +#if defined(pte_offset_atomic)
2852 +#define NV_PTE_OFFSET(address, pmd) \
2853 + ({ \
2854 + pte_t *__pte; \
2855 + __pte = pte_offset_atomic(pmd, address); \
2856 + NV_PMD_UNMAP(pmd); __pte; \
2857 + })
2858 +#define NV_PTE_UNMAP(pte) pte_kunmap(pte);
2859 +#elif defined(pte_offset)
2860 +#define NV_PTE_OFFSET(address, pmd) \
2861 + ({ \
2862 + pte_t *__pte; \
2863 + __pte = pte_offset(pmd, address); \
2864 + NV_PMD_UNMAP(pmd); __pte; \
2865 + })
2866 +#define NV_PTE_UNMAP(pte)
2867 +#else
2868 +#define NV_PTE_OFFSET(address, pmd) \
2869 + ({ \
2870 + pte_t *__pte; \
2871 + __pte = pte_offset_map(pmd, address); \
2872 + NV_PMD_UNMAP(pmd); __pte; \
2873 + })
2874 +#define NV_PTE_UNMAP(pte) pte_unmap(pte);
2875 +#endif
2877 +#define NV_PTE_PRESENT(pte) \
2878 + ({ \
2879 + if ((pte != NULL) && !pte_present(*pte)) \
2880 + { \
2881 + NV_PTE_UNMAP(pte); \
2882 + pte = NULL; /* mark invalid */ \
2883 + } \
2884 + pte != NULL; \
2885 + })
2887 +#define NV_PTE_VALUE(pte) \
2888 + ({ \
2889 + unsigned long __pte_value = pte_val(*pte); \
2890 + NV_PTE_UNMAP(pte); \
2891 + __pte_value; \
2892 + })
2895 +#define NV_PAGE_ALIGN(addr) ( ((addr) + PAGE_SIZE - 1) / PAGE_SIZE)
2896 +#define NV_MASK_OFFSET(addr) ( (addr) & (PAGE_SIZE - 1) )
2901 +/* cache flushing
2902 + * when allocating new pages, we convert the kernel mapping from cached to
2903 + * uncached to avoid cache aliasing. one problem with this is that cpus can
2904 + * still contain data cached from these pages, in addition to stale ptes that
2905 + * are cached and think the pages are still cached. normally, the cpu's self
2906 + * snoop (SS) capability would catch this between cpus, but if the pages are
2907 + * mapped through the agp aperture, SS is not capable of detecting these
2908 + * conflicts. we try to rely on the kernel's provided interfaces when possible,
2909 + * but need additional flushing on earlier kernels.
2910 + */
2911 +#if defined(KERNEL_2_4)
2912 +/* wrap CACHE_FLUSH so we can pass it to smp_call_function */
2913 +static void cache_flush(void *p)
2915 + CACHE_FLUSH();
2917 +#endif
2920 + * 2.4 kernels handle flushing in the change_page_attr() call, but kernels
2921 + * earlier than 2.4.27 don't flush on cpus that support Self Snoop, so we
2922 + * manually flush on these kernels (actually, we go ahead and flush on all
2923 + * 2.4 kernels, as it's possible some others may be missing this fix and
2924 + * we'd prefer to be a little slower flushing caches than hanging the
2925 + * system. 2.6 kernels split the flushing out to a seperate call,
2926 + * global_flush_tlb(), so we rely on that.
2927 + */
2928 +static void nv_flush_caches(void)
2930 +#if defined(KERNEL_2_4)
2931 +#ifdef CONFIG_SMP
2932 + smp_call_function(cache_flush, NULL, 1, 1);
2933 +#endif
2934 + cache_flush(NULL);
2935 +#else
2936 + global_flush_tlb();
2937 +#endif
2940 +static inline int nv_calc_order(unsigned int size)
2942 + int order = 0;
2943 + while ( ((1 << order) * PAGE_SIZE) < (size))
2945 + order++;
2947 + return order;
2951 +#if defined(NV_CHANGE_PAGE_ATTR_PRESENT)
2952 +static inline void NV_SET_PAGE_ATTRIB_UNCACHED(unsigned long physaddr)
2954 + struct page *page = virt_to_page(__va(physaddr));
2955 + change_page_attr(page, 1, PAGE_KERNEL_NOCACHE);
2957 +static inline void NV_SET_PAGE_ATTRIB_CACHED(unsigned long physaddr)
2959 + struct page *page = virt_to_page(__va(physaddr));
2960 + change_page_attr(page, 1, PAGE_KERNEL);
2962 +#else
2963 +#define NV_SET_PAGE_ATTRIB_UNCACHED(page_list)
2964 +#define NV_SET_PAGE_ATTRIB_CACHED(page_list)
2965 +#endif
2967 +#endif /* _NVA_VM_H_ */
2969 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvmain.c NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvmain.c
2970 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvmain.c 2005-10-21 20:59:44.000000000 -0500
2971 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvmain.c 2008-08-14 10:13:48.000000000 -0500
2972 @@ -2074,7 +2074,7 @@
2973 card_names[pci_id->driver_data], devs->hwbase->apubase,devs->hwbase->apuirq);
2976 - if(request_irq(devs->hwbase->apuirq,&Nvapu_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], devs)) {
2977 + if(request_irq(devs->hwbase->apuirq,&Nvapu_interrupt, IRQF_SHARED, card_names[pci_id->driver_data], devs)) {
2978 printk(KERN_ERR "Nvsound: IRQ in use \n");
2979 ret = -EBUSY;
2980 NvRelease_Resources(devs);
2981 @@ -2162,7 +2162,7 @@
2984 // ISR should be register after the initialization
2985 - if(request_irq(devs->hwbase->aciirq,&Nvaci_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], devs)) {
2986 + if(request_irq(devs->hwbase->aciirq,&Nvaci_interrupt, IRQF_SHARED, card_names[pci_id->driver_data], devs)) {
2987 printk(KERN_ERR "Nvsound: IRQ in use \n");
2988 NvRelease_Resources(devs);
2989 ret = -EBUSY;
2990 @@ -2188,7 +2188,7 @@
2994 -MODULE_PARM(vapu_enable, "i");
2995 +module_param(vapu_enable, int, 0444);
2996 #define NVAUDIO_MODULE_NAME "nforce_audio"
2997 static struct pci_driver Nvaudio_pci_driver = {
2998 name: NVAUDIO_MODULE_NAME,
2999 @@ -2205,7 +2205,7 @@
3000 int ret = 0;
3001 printk(KERN_INFO "Nvsound: Nvidia Audio Init Module, " __TIME__ " " __DATE__ " version %s \n",
3002 DRIVERVER);
3003 - ret = pci_module_init(&Nvaudio_pci_driver);
3004 + ret = ret = pci_register_driver(&Nvaudio_pci_driver);
3005 return ret;
3008 diff -Naur NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvmain.c.orig NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvmain.c.orig
3009 --- NFORCE-Linux-x86-1.0-0310-pkg1.old/nvsound/main/nvmain.c.orig 1969-12-31 18:00:00.000000000 -0600
3010 +++ NFORCE-Linux-x86-1.0-0310-pkg1/nvsound/main/nvmain.c.orig 2005-10-21 20:59:44.000000000 -0500
3011 @@ -0,0 +1,2221 @@
3013 +/****************************************************************** \
3014 +|* *|
3015 +|* *|
3016 +|* (c) NVIDIA Corporation. All rights reserved *|
3017 +|* *|
3018 +|* THE INFORMATION CONTAINED HEREIN IS PROPRIETARY AND *|
3019 +|* CONFIDENTIAL *|
3020 +|* TO NVIDIA, CORPORATION. USE, REPORDUCTION OR DISCLOSURE TO ANY *|
3021 +|* THIRD PARTY IS SUBJECT TO WRITTEN PRE-APPROVAL BY NVIDIA CORP. *|
3022 +|* *|
3023 +|* THE INFORMATION CONTAINED HEREIN IS PROVIDED "AS IS" WITHOUT *|
3024 +|* EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING ALL IMPLIED *|
3025 +|* WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS *|
3026 +|* FOR A PARTICULAR PURPOSE. *|
3027 +|* *|
3028 +********************************************************************/
3029 +/*******************************************************************
3031 +* nvmain.c
3033 +* Descripion - Main code for the driver
3035 +********************************************************************
3038 +#include <linux/module.h>
3039 +#include <linux/version.h>
3040 +#include "nvhw.h"
3041 +#include "nvapucalls.h"
3043 +#define PRINT_IOCTL 0
3044 +#define ENABLE_MONO 1
3046 +#ifndef PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO
3047 +#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1
3048 +#endif
3050 +#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
3051 +#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a
3052 +#endif
3054 +#ifndef PCI_DEVICE_ID_NVIDIA_MCP2S_AUDIO
3055 +#define PCI_DEVICE_ID_NVIDIA_MCP2S_AUDIO 0x008a
3056 +#endif
3058 +#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
3059 +#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
3060 +#endif
3062 +#ifndef PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO
3063 +#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea
3064 +#endif
3066 +#ifndef PCI_DEVICE_ID_NVIDIA_CK804_AUDIO
3067 +#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059
3068 +#endif
3070 +#ifndef PCI_DEVICE_ID_NVIDIA_MCP04_AUDIO
3071 +#define PCI_DEVICE_ID_NVIDIA_MCP04_AUDIO 0x003a
3072 +#endif
3074 +#ifndef PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO
3075 +#define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO 0x026B
3076 +#endif
3078 +#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_CONTROLLER
3079 +#define PCI_DEVICE_ID_NVIDIA_MCP2_CONTROLLER 0x006b
3080 +#endif
3082 +#ifndef PCI_DEVICE_ID_NVIDIA_MCP1_CONTROLLER
3083 +#define PCI_DEVICE_ID_NVIDIA_MCP1_CONTROLLER 0x01b0
3084 +#endif
3085 +enum {
3086 + NVIDIA_NFORCE2_CONTROLLER=0,
3087 + NVIDIA_NFORCE1_CONTROLLER,
3088 + NVIDIA_NFORCE1,
3089 + NVIDIA_NFORCE2,
3090 + NVIDIA_NFORCE3,
3091 + NVIDIA_MCP2S,
3092 + NVIDIA_CK8S,
3093 + NVIDIA_CK804,
3094 + NVIDIA_MCP04,
3095 + NVIDIA_MCP51
3097 +static char * card_names[] = {
3098 + "NVIDIA nForce2 Controller",
3099 + "NVIDIA nForce1 Controller",
3100 + "NVIDIA nForce1 Audio",
3101 + "NVIDIA nForce2 Audio",
3102 + "NVIDIA Hammer Audio",
3103 + "NVIDIA MCP2S Audio",
3104 + "NVIDIA CK8S Audio",
3105 + "NVIDIA CK804 Audio",
3106 + "NVIDIA MCP04 Audio",
3107 + "NVIDIA MCP51 Audio"
3109 +static struct pci_device_id Nvaudio_pci_tbl[] = {
3110 + {PCI_VENDOR_ID_NVIDIA,PCI_DEVICE_ID_NVIDIA_MCP2_CONTROLLER,
3111 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE2_CONTROLLER},
3112 + {PCI_VENDOR_ID_NVIDIA,PCI_DEVICE_ID_NVIDIA_MCP1_CONTROLLER,
3113 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE1_CONTROLLER},
3114 + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO,
3115 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE1},
3116 + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO,
3117 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE2},
3118 + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO,
3119 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE3},
3120 + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2S_AUDIO,
3121 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_MCP2S},
3122 + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO,
3123 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_CK8S},
3124 + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_AUDIO,
3125 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_CK804},
3126 + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP04_AUDIO,
3127 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_MCP04},
3128 + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO,
3129 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_MCP51},
3130 + {0,}
3133 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
3134 +MODULE_LICENSE("NVIDIA");
3135 +#endif
3137 +MODULE_DEVICE_TABLE(pci, Nvaudio_pci_tbl);
3138 +static Nvaudio_card *devs = NULL;
3139 +static unsigned int vapu_enable = 0;
3141 +static int Nvadd_wave_device(Nvaudio_card *card, struct file *file, int dev_type);
3142 +static int alloc_frags(Nvaudio_card *card, Nvaudio_stream *stream, unsigned long count);
3143 +static int dealloc_frags(Nvaudio_stream *nvstream, void *pDevice);
3144 +static void Nvfree_wave_device(Nvaudio_card *card, Nvaudio_wavedev *nvwavdev);
3145 +static void Nvremove_wave_device(Nvaudio_card *card, Nvaudio_wavedev *nvwavdev);
3146 +static Nvaudio_wavedev* Nvfind_wave_device(Nvaudio_card *card, struct file *file);
3147 +static void Nvstop_wave(Nvaudio_card *card, Nvaudio_stream *nvstream, int type);
3148 +static unsigned long Nvfill_mem(Nvaudio_card *card, Nvaudio_stream *nvstream, const char *mem, unsigned long size);
3149 +static unsigned long Nvget_mem(Nvaudio_card *card, Nvaudio_stream *nvstream, char *mem, unsigned long size);
3150 +static void drain_dac(Nvaudio_card *card, Nvaudio_wavedev *nvwavdev, int nonblock);
3151 +static int Nvaudio_release(struct inode *inode, struct file *file);
3152 +static int Nvaudio_open(struct inode *inode, struct file *file);
3153 +static int Nvfree_reopenStream(Nvaudio_wavedev *nvwavdev, struct file *file);
3155 +#define INT_MASK 0xAF7
3157 +void playback_tasklet(unsigned long cardinfo);
3158 +void record_tasklet(unsigned long cardinfo);
3159 +DECLARE_TASKLET(playbacktask,playback_tasklet,0);
3160 +DECLARE_TASKLET(recordtask,record_tasklet,0);
3162 +////////////////////////////////////////////////////////////////////////
3163 +// APU ISR FUNCTION which in turn schedule a tasklet
3164 +////////////////////////////////////////////////////////////////////////
3165 +static irqreturn_t Nvapu_interrupt(int irq, void* dev_id, struct pt_regs *regs)
3167 + int status = 0;
3168 + Nvaudio_card *card = (Nvaudio_card *)dev_id;
3170 + spin_lock(&card->play_lock);
3171 + status = Nv_ApuISR();
3173 + if(!status){
3174 + tasklet_schedule(&playbacktask);
3175 + }else {
3176 + // not our irq
3177 + spin_unlock(&card->play_lock);
3178 + return IRQ_NONE;
3181 + spin_unlock(&card->play_lock);
3182 + return IRQ_HANDLED;
3185 +////////////////////////////////////////////////////////////////////////
3186 +// APU ISR tasklet - function to verify all running playback streams
3187 +////////////////////////////////////////////////////////////////////////
3188 +void playback_tasklet(unsigned long cardinfo)
3190 + mem_buf_t *cur = NULL;
3191 + unsigned long flags = 0;
3192 + unsigned long count = 0, remaining = 0;
3193 + long long curposn = 0;
3194 + Nvaudio_stream *nvstream = NULL;
3195 + Nvaudio_wavedev *nvwavdev = NULL;
3197 + spin_lock_irqsave(&devs->list_lock,flags);
3198 + nvwavdev = devs->wave_head;
3199 + spin_unlock_irqrestore(&devs->list_lock,flags);
3201 +// if(vapu_enable)
3202 + Nv_VapuDpc();
3203 + while(nvwavdev) {
3204 + if(nvwavdev->playback_stream.enable || nvwavdev->playback_stream.mapped ) {
3205 + nvstream = &nvwavdev->playback_stream;
3206 + curposn = Nv_getposition(nvstream->wavestream);
3207 + /*if((!curposn) && (nvstream->total_played < nvstream->total_sent)){
3208 + nvstream->total_played = nvstream->total_sent;
3209 + }
3210 + if(!curposn){
3211 + wake_up_interruptible(&nvstream->wait);
3212 + }*/
3213 + if(curposn > nvstream->lastposition) {
3214 + count = (unsigned long)(curposn - nvstream->lastposition);
3215 + nvstream->total_played +=count;
3216 + nvstream->lastposition = curposn;
3217 + }else{
3218 + wake_up_interruptible(&nvstream->wait);
3221 + while(count > 0){
3222 + cur = (mem_buf_t *) &(nvstream->buf[nvstream->drain_index]);
3223 + remaining = cur->count - cur->xfer;
3224 + // assert if page not in use - starving case
3225 + if(!cur->in_use) {
3226 + count = 0;
3227 + break;
3229 + if(count < remaining){
3230 + cur->xfer += count;
3231 + count = 0;
3232 + }else {
3233 + nvstream->drain_index = (nvstream->drain_index + 1) % nvstream->num_frags;
3234 + if(nvstream->mapped){
3235 + cur->xfer = 0;
3236 + Nv_passdown(nvstream->wavestream,cur->page,cur->count,nvstream->drain_index,FALSE);
3237 + }else{
3238 + cur->xfer = cur->count;
3239 + cur->count = 0;
3240 + cur->in_use = FALSE;
3241 + wake_up_interruptible(&nvstream->wait);
3243 + count -= remaining;
3246 + }
3247 + spin_lock_irqsave(&devs->list_lock,flags);
3248 + nvwavdev = nvwavdev->next;
3249 + spin_unlock_irqrestore(&devs->list_lock,flags);
3250 + }
3253 +////////////////////////////////////////////////////////////////////////
3254 +// ACI ISR - right now it doesnot get hit as we didnot request interrupt
3255 +// on buffer completion
3256 +////////////////////////////////////////////////////////////////////////
3257 +static irqreturn_t Nvaci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
3259 + int status = 0;
3260 + u32 globstat = 0;
3261 + Nvaudio_card *card = (Nvaudio_card *)dev_id;
3263 + //spin_lock(&card->play_lock);
3264 + spin_lock(&card->rec_lock);
3265 + globstat = inl(card->hwbase->acibase + 0x30);
3267 + if(!(globstat & INT_MASK)) {
3268 + spin_unlock(&card->rec_lock);
3269 + // spin_unlock(&card->play_lock);
3270 + return IRQ_NONE;
3273 + status = Nv_AciISR();
3274 + if(!status) {
3275 + // need this to run in case of spdif only - with or without apu
3276 + if( (card->hwbase->acipresent) && ( (!(card->hwbase->apupresent)) || card->ac3_in_use ) ){
3277 + tasklet_schedule(&playbacktask);
3279 + tasklet_schedule(&recordtask);
3281 + spin_unlock(&card->rec_lock);
3282 + //spin_unlock(&card->play_lock);
3283 + return IRQ_HANDLED;
3286 +////////////////////////////////////////////////////////////////////////
3287 +// ACI ISR tasklet - function to verify running record
3288 +////////////////////////////////////////////////////////////////////////
3289 +void record_tasklet(unsigned long cardinfo)
3291 + mem_buf_t *cur = NULL;
3292 + unsigned long flags = 0;
3293 + unsigned long count = 0, remaining = 0;
3294 + long long curposn = 0;
3295 + Nvaudio_stream *nvstream = NULL;
3296 + Nvaudio_wavedev *nvwavdev = NULL;
3297 + spin_lock_irqsave(&devs->list_lock,flags);
3298 + nvwavdev = devs->wave_head;
3299 + spin_unlock_irqrestore(&devs->list_lock,flags);
3300 + while(nvwavdev) {
3301 + if(nvwavdev->record_stream.enable || nvwavdev->record_stream.mapped ) {
3302 + nvstream = &nvwavdev->record_stream;
3303 + curposn = Nv_getposition(nvstream->wavestream);
3305 + if(curposn > nvstream->lastposition) {
3306 + count = (unsigned long)(curposn - nvstream->lastposition);
3307 + nvstream->total_played +=count;
3308 + nvstream->lastposition = curposn;
3309 + }else {
3310 + wake_up_interruptible(&nvstream->wait);
3313 + while(count > 0){
3314 + cur = &(nvstream->buf[nvstream->fill_index]);
3315 + remaining = cur->count - cur->xfer;
3316 + // assert if page not in use - starving case
3317 + if(!cur->in_use) {
3318 + count = 0;
3319 + break;
3321 + if(count < remaining){
3322 + cur->xfer += count;
3323 + count = 0;
3324 + }else {
3325 + nvstream->fill_index = (nvstream->fill_index + 1) % nvstream->num_frags;
3326 + if(nvstream->mapped){
3327 + cur->xfer = 0;
3328 + Nv_passdown(nvstream->wavestream,cur->page,cur->count,nvstream->fill_index,FALSE);
3329 + }else{
3330 + cur->xfer = cur->count;
3331 + cur->count = 0;
3332 + cur->in_use = FALSE;
3333 + wake_up_interruptible(&nvstream->wait);
3335 + count -= remaining;
3338 + }
3339 + spin_lock_irqsave(&devs->list_lock,flags);
3340 + nvwavdev = nvwavdev->next;
3341 + spin_unlock_irqrestore(&devs->list_lock,flags);
3342 + }
3344 +////////////////////////////////////////////////////////////////////////
3345 +// Deallocate the dma buffer for each stream
3346 +////////////////////////////////////////////////////////////////////////
3347 +static int dealloc_frags(Nvaudio_stream *nvstream, void *pDevice)
3349 + struct page *page = NULL, *pend = NULL;
3350 + if (nvstream->vir_dmabuf) {
3351 + // undo marking the pages as reserved
3352 + pend = virt_to_page((u8 *)nvstream->vir_dmabuf + ((PAGE_SIZE << nvstream->buf_order) - 1));
3353 + for (page = virt_to_page(nvstream->vir_dmabuf); page <= pend; page++) {
3354 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3355 + mem_map_unreserve(page);
3356 +#else
3357 + ClearPageReserved(page);
3358 +#endif
3361 + if(pDevice) {
3362 + pci_free_consistent(pDevice, PAGE_SIZE << nvstream->buf_order,
3363 + nvstream->vir_dmabuf, nvstream->dma_handle);
3366 + return 0;
3368 +////////////////////////////////////////////////////////////////////////
3369 +// Allocate the dma buffer for each stream
3370 +////////////////////////////////////////////////////////////////////////
3371 +static int alloc_frags(Nvaudio_card * card, Nvaudio_stream *stream, unsigned long count)
3373 + struct page *page = NULL, *pend = NULL;
3374 + unsigned long page_addr = 0;
3375 + int i = 0;
3376 + void *pDevice = NULL;
3377 + unsigned long order = 0;
3378 + order = NV_DEFAULTORDER;
3380 + // Find which device is present or not first
3381 + if(card->hwbase->apupresent) {
3382 + pDevice = card->hwbase->pApu_dev;
3384 + else { // assume aci is present
3385 + pDevice = card->hwbase->pAci_dev;
3387 + if(!pDevice) { return -EBUSY;}
3389 + stream->vir_dmabuf = pci_alloc_consistent(pDevice,
3390 + PAGE_SIZE << order,
3391 + &stream->dma_handle);
3392 + if(!stream->vir_dmabuf){
3393 + printk("Nvsound: Unable to allocate the dmabuffer for the stream \n");
3394 + return -ENOMEM;
3397 + stream->buf_order = order;
3399 + // now mark the pages as reserved;
3400 + // otherwise remap_page_range doesn't do what we want
3402 + pend = virt_to_page((u8 *)stream->vir_dmabuf + ((PAGE_SIZE << order) - 1));
3403 + for (page = virt_to_page(stream->vir_dmabuf); page <= pend; page++) {
3405 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3406 + mem_map_reserve(page);
3407 +#else
3408 + SetPageReserved(page);
3409 +#endif
3412 + page_addr = (unsigned long) stream->vir_dmabuf;
3413 + for(i=0; i < count; i++) {
3414 + stream->buf[i].page = (void *)page_addr;
3415 + stream->buf[i].in_use = FALSE;
3416 + stream->buf[i].count = 0;
3417 + page_addr += stream->frag_size;
3420 + return 0;
3423 +////////////////////////////////////////////////////////////////////////
3424 +// Free a wave device - free newstream created and deallocate the dma for
3425 +// hardware to access
3426 +////////////////////////////////////////////////////////////////////////
3427 +static void Nvfree_wave_device(Nvaudio_card *card, Nvaudio_wavedev *nvwavdev)
3429 + unsigned long flags = 0;
3430 + void* pDevice = 0;
3431 + // Find which device is present or not first
3432 + if(card->hwbase->apupresent) {
3433 + pDevice = card->hwbase->pApu_dev;
3435 + else { // assume aci is present
3436 + pDevice = card->hwbase->pAci_dev;
3439 + if (nvwavdev->playback_stream.wavestream) {
3440 + if(!nvwavdev->playback_stream.verifyac3)
3441 + spin_lock_irqsave(&card->play_lock,flags);
3442 + Nv_FreeNewstream(nvwavdev->playback_stream.wavestream);
3443 + if(!nvwavdev->playback_stream.verifyac3)
3444 + spin_unlock_irqrestore(&card->play_lock,flags);
3445 + if(nvwavdev->playback_stream.verifyac3) {
3446 + nvwavdev->playback_stream.verifyac3 = 0;
3447 + card->ac3_in_use = 0;
3451 + if (nvwavdev->record_stream.wavestream) {
3452 + spin_lock_irqsave(&card->rec_lock, flags);
3453 + Nv_FreeNewstream(nvwavdev->record_stream.wavestream);
3454 + spin_unlock_irqrestore(&card->rec_lock, flags);
3457 + // dealloc frags for playback
3458 + dealloc_frags(&nvwavdev->playback_stream,pDevice);
3460 + // dealloc frags for record
3461 + dealloc_frags(&nvwavdev->record_stream,pDevice);
3463 + kfree(nvwavdev);
3464 + return;
3466 +////////////////////////////////////////////////////////////////////////
3467 +// ADD a wave device - create a newstream and allocate the dma for
3468 +// hardware to access
3469 +////////////////////////////////////////////////////////////////////////
3470 +static int Nvadd_wave_device(Nvaudio_card *card, struct file *file, int dev_type)
3472 + unsigned long flags = 0;
3473 + int status = 0;
3474 + int is_apupresent = 0;
3475 + Nvaudio_wavedev *nvwavdev;
3476 + int is_playback = file->f_mode & FMODE_WRITE;
3477 + int is_record = file->f_mode & FMODE_READ;
3479 + if(card->hwbase->apupresent) is_apupresent = 1;
3481 + // allow only one rec - This cause issue with Quake and other app using record section
3482 + //if(is_record && card->rec_in_use)
3483 + // return -EBUSY;
3485 + nvwavdev = (Nvaudio_wavedev *)kmalloc(sizeof(Nvaudio_wavedev),GFP_KERNEL);
3486 + if(!nvwavdev) {
3487 + return -ENOMEM;
3489 + memset(nvwavdev,0,sizeof(Nvaudio_wavedev));
3491 + //Set default data format
3492 + nvwavdev->playback_stream.fmt.dwSampleRate = DEFAULT_SAMPLERATE;
3493 + nvwavdev->playback_stream.fmt.wChannels = 2; //stereo
3494 + nvwavdev->playback_stream.fmt.wBitsPerSample = 16;
3495 + nvwavdev->playback_stream.fmt.wformat = AFMT_S16_LE;
3496 + init_waitqueue_head(&nvwavdev->playback_stream.wait);
3498 + nvwavdev->record_stream.fmt.dwSampleRate = DEFAULT_SAMPLERATE;
3499 + nvwavdev->record_stream.fmt.wChannels = 2; //stereo
3500 + nvwavdev->record_stream.fmt.wBitsPerSample = 16;
3501 + nvwavdev->record_stream.fmt.wformat = AFMT_S16_LE;
3502 + nvwavdev->record_stream.Channels = 2;
3503 + init_waitqueue_head(&nvwavdev->record_stream.wait);
3505 + // fixed size buffer are provided - need to verify whether it
3506 + // affect any apps
3507 + nvwavdev->playback_stream.frag_size = NVDEFAULT_FRAGSIZE;
3508 + nvwavdev->playback_stream.num_frags = NVDEFAULT_FRAGS;
3509 + nvwavdev->record_stream.frag_size = NVDEFAULT_FRAGSIZE;
3510 + nvwavdev->record_stream.num_frags = NVDEFAULT_FRAGS;
3512 + nvwavdev->fp = file;
3514 + if((is_record) && (!card->rec_in_use)) {
3515 + if(alloc_frags(card,&(nvwavdev->record_stream),nvwavdev->record_stream.num_frags)) {
3516 + printk("Nvsound: Unable to allocate the pages for the record stream \n");
3517 + Nvfree_wave_device(card,nvwavdev);
3518 + return -ENOMEM;
3520 + status = Nv_CreateNewstream(&(nvwavdev->record_stream.fmt),NVDIRREC,&(nvwavdev->record_stream.wavestream),is_apupresent);
3521 + if(status) {
3522 + printk("Nvsound: Unable to Create a NewStream for recording \n");
3523 + Nvfree_wave_device(card,nvwavdev);
3524 + return -ENOMEM;
3526 + card->rec_in_use = TRUE;
3529 + if(is_playback) {
3530 + if(alloc_frags(card,&(nvwavdev->playback_stream),nvwavdev->playback_stream.num_frags)) {
3531 + printk("Nvsound: Unable to allocate the pages for the playback stream \n");
3532 + Nvfree_wave_device(card,nvwavdev);
3533 + return -ENOMEM;
3535 + status = Nv_CreateNewstream(&(nvwavdev->playback_stream.fmt),NVDIRPLAY,&(nvwavdev->playback_stream.wavestream),is_apupresent);
3536 + if(status) {
3537 + printk("Nvsound: Unable to Create a NewStream for apu \n");
3538 + Nvfree_wave_device(card,nvwavdev);
3539 + return -ENOMEM;
3543 + spin_lock_irqsave(&card->list_lock,flags);
3544 + // link the device to the list
3545 + if(card->wave_head == NULL) {
3546 + card->wave_head = nvwavdev;
3547 + card->wave_tail = nvwavdev;
3549 + else {
3550 + card->wave_tail->next = nvwavdev;
3551 + nvwavdev->prev = card->wave_tail;
3552 + card->wave_tail = nvwavdev;
3554 + spin_unlock_irqrestore(&card->list_lock,flags);
3555 + return 0;
3558 +////////////////////////////////////////////////////////////////////////
3559 +// Function to find the wave device from the device list
3560 +////////////////////////////////////////////////////////////////////////
3561 +static Nvaudio_wavedev* Nvfind_wave_device(Nvaudio_card *card, struct file *file)
3563 + unsigned long flags = 0;
3564 + Nvaudio_wavedev *nvwavdev = NULL;
3566 + // could use reader/writer spinlocks
3567 + spin_lock_irqsave(&card->list_lock,flags);
3569 + nvwavdev = card->wave_head;
3571 + while (nvwavdev) {
3572 + if (nvwavdev->fp == file)
3573 + break;
3574 + nvwavdev = nvwavdev->next;
3576 + spin_unlock_irqrestore(&card->list_lock,flags);
3578 + return nvwavdev;
3581 +////////////////////////////////////////////////////////////////////////
3582 +// Function to remove a wave device from the list
3583 +////////////////////////////////////////////////////////////////////////
3584 +static void Nvremove_wave_device(Nvaudio_card *card, Nvaudio_wavedev *nvwavdev)
3586 + unsigned long flags = 0;
3587 + spin_lock_irqsave(&card->list_lock,flags);
3588 + // unlink the wave device
3589 + if(nvwavdev == card->wave_head) {
3590 + card->wave_head = nvwavdev->next;
3591 + if(card->wave_head)
3592 + card->wave_head->prev = NULL;
3593 + } else {
3594 + nvwavdev->prev->next = nvwavdev->next;
3595 + if(nvwavdev->next)
3596 + nvwavdev->next->prev = nvwavdev->prev;
3597 + else
3598 + card->wave_tail = nvwavdev->prev;
3600 + spin_unlock_irqrestore(&card->list_lock,flags);
3601 + Nvfree_wave_device(card, nvwavdev);
3604 +////////////////////////////////////////////////////////////////////////
3605 +// Nvaudio_read which helps to pass the recorded data from hw to user.
3606 +// It is filled by the dma machine and drained by this loop.
3607 +////////////////////////////////////////////////////////////////////////
3608 +static ssize_t Nvaudio_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
3610 + size_t xfer =0, received = 0;
3611 + Nvaudio_wavedev *nvwavdev = NULL;
3612 + Nvaudio_stream *nvstream = NULL;
3613 + unsigned long flags = 0;
3614 + Nvaudio_card *card = (Nvaudio_card *)file->private_data;
3615 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3616 + DECLARE_WAITQUEUE(waita,current);
3617 +#else
3618 + DEFINE_WAIT(waita);
3619 +#endif
3621 + nvwavdev = Nvfind_wave_device(card,file);
3622 + if(!nvwavdev) {
3623 + printk("Nvsound: Unable to find any wave device \n");
3624 + return -ENXIO;
3627 + nvstream = &nvwavdev->record_stream;
3629 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
3630 + if( ppos != &file->f_pos)
3631 + return -ESPIPE;
3632 +#endif
3634 + if(!nvstream->wavestream) {
3635 + // Hack Team Speak to sound - if rec already in use
3636 + return count;
3638 + if(nvstream->mapped)
3639 + return -ENXIO;
3641 + if (!access_ok(VERIFY_WRITE, buffer, count))
3642 + return -EFAULT;
3644 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3645 + add_wait_queue(&nvstream->wait,&waita);
3646 +#endif
3648 + while(received < count) {
3649 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3650 + set_current_state(TASK_INTERRUPTIBLE);
3651 +#else
3652 + prepare_to_wait(&nvstream->wait,&waita,TASK_INTERRUPTIBLE);
3653 +#endif
3654 + //if not enabled - Nvget_mem will add first buffers, else
3655 + //copy the completed buffers to user space and queue if not
3656 + //filled completely
3657 + xfer = Nvget_mem(card,nvstream,buffer+received,(count-received));
3658 + received += xfer;
3660 + if(!nvstream->enable) {
3661 + spin_lock_irqsave(&card->rec_lock,flags);
3662 + Nv_start(nvstream->wavestream);
3663 + nvstream->enable = TRUE;
3664 + spin_unlock_irqrestore(&card->rec_lock,flags);
3666 + if(received < count) {
3667 + if(file->f_flags & O_NONBLOCK) {
3668 + received = (received)? (ssize_t)received: -EAGAIN;
3669 + goto recdone;
3672 + //interruptible_sleep_on(&nvstream->wait);
3673 + schedule_timeout(15);
3674 + if(signal_pending(current)) {
3675 + received = (received)? (ssize_t) received: -ERESTARTSYS;
3676 + goto recdone;
3678 + continue;
3682 +recdone:
3683 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3684 + set_current_state(TASK_RUNNING);
3685 + remove_wait_queue(&nvstream->wait,&waita);
3686 +#else
3687 + finish_wait(&nvstream->wait,&waita);
3688 +#endif
3689 + return received;
3692 +////////////////////////////////////////////////////////////////////////
3693 +// Function that drain remaining buffered data
3694 +////////////////////////////////////////////////////////////////////////
3695 +static void drain_dac(Nvaudio_card *card, Nvaudio_wavedev *nvwavdev, int nonblock)
3697 + int status = 0;
3698 + unsigned long xferorig = 0;
3699 + unsigned long flags = 0;
3700 + mem_buf_t *mb = NULL;
3701 + Nvaudio_stream *nvstream = NULL;
3702 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3703 + DECLARE_WAITQUEUE(wait,current);
3704 +#else
3705 + DEFINE_WAIT(wait);
3706 +#endif
3708 + //printk("Nvsound: DRAIN_DAC GET CALLED \n");
3709 + nvstream = &(nvwavdev->playback_stream);
3710 + if(!nvstream) return;
3711 + mb = &(nvstream->buf[nvstream->fill_index]);
3713 + if (nvstream->mapped) {
3714 + return;
3717 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3718 + add_wait_queue(&nvstream->wait,&wait);
3719 +#endif
3720 + while (nvstream->total_played < nvstream->total_sent) {
3721 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3722 + set_current_state(TASK_INTERRUPTIBLE);
3723 +#else
3724 + prepare_to_wait(&nvstream->wait,&wait,TASK_INTERRUPTIBLE);
3725 +#endif
3726 + if (!mb->in_use && mb->count) {
3727 + mb->in_use=TRUE;
3728 + xferorig = mb->xfer;
3729 + mb->xfer=0;
3730 + spin_lock_irqsave(&card->play_lock,flags);
3731 + //printk("Nvsound: DRAIN_DAC pass down the buffer \n");
3732 + status = Nv_passdown(nvstream->wavestream, mb->page, mb->count,nvstream->fill_index,TRUE);
3733 + if(status) {
3734 + mb->in_use = FALSE;
3735 + mb->xfer = xferorig;
3737 + spin_unlock_irqrestore(&card->play_lock,flags);
3738 + }else{
3739 + break;
3742 + if (!nvstream->enable) {
3743 + //printk("Nvsound: DRAIN_DAC enable the stream \n");
3744 + spin_lock_irqsave(&card->play_lock, flags);
3745 + Nv_start(nvstream->wavestream);
3746 + nvstream->enable = TRUE;
3747 + spin_unlock_irqrestore(&card->play_lock, flags);
3749 + if(nonblock)
3750 + break;
3751 + //interruptible_sleep_on_timeout(&nvstream->wait,10);
3752 + schedule_timeout(10);
3753 + if (signal_pending(current)) {
3754 + break;
3756 + continue;
3758 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3759 + set_current_state(TASK_RUNNING);
3760 + remove_wait_queue(&nvstream->wait,&wait);
3761 +#else
3762 + finish_wait(&nvstream->wait,&wait);
3763 +#endif
3765 + //printk("Nvsound: DRAIN_DAC left \n");
3768 +/////////////////////////////////////////////////////////////////////////
3769 +// Funtion to verify for ac3 data.
3770 +// This check the first few data for ac3 signature.
3771 +////////////////////////////////////////////////////////////////////////
3772 +/*static int Nvaudio_verifyac3(Nvaudio_stream *nvstream,const char *buffer, size_t count)
3774 + unsigned short ac3data[0x40];
3775 + int ac3size = 0, i = 0;
3776 + ac3size = sizeof(short) * 0x40;
3777 + memset(ac3data, 0, ac3size);
3779 + if(count < ac3size) return 0;
3780 + copy_from_user(ac3data,buffer,ac3size);
3782 + for( i=0; i < 0x40; i++) {
3783 + if(ac3data[i] == 0xF872) {
3784 + i++;
3785 + if(ac3data[i] == 0x4E1F) {
3786 + nvstream->fmt.wformat = AFMT_AC3;
3787 + return 1;
3791 + return 0;
3792 +}*/
3793 +////////////////////////////////////////////////////////////////////////
3794 +// Function that passed the data from user to hw for playback.
3795 +// in this loop, sent signifies the amount of data that is waiting
3796 +// to be dma to the soundcard.
3797 +// it is drained by the dma machine and filled by this loop.
3798 +////////////////////////////////////////////////////////////////////////
3799 +static ssize_t Nvaudio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
3801 + size_t xfer =0, sent = 0;
3802 + Nvaudio_wavedev *nvwavdev = NULL;
3803 + Nvaudio_stream *nvstream = NULL;
3804 + unsigned long flags = 0;
3805 + Nvaudio_card *card = (Nvaudio_card *)file->private_data;
3807 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3808 + DECLARE_WAITQUEUE(waitb,current);
3809 +#else
3810 + DEFINE_WAIT(waitb);
3811 +#endif
3813 + if(!count)
3814 + return 0;
3816 + nvwavdev = Nvfind_wave_device(card,file);
3817 + if(!nvwavdev) {
3818 + printk("Nvsound: Unable to find any wave device \n");
3819 + return -ENXIO;
3822 + nvstream = &nvwavdev->playback_stream;
3823 + /*if((nvstream->verifyac3 == 0) && (card->ac3_in_use == 0)) {
3824 + nvstream->verifyac3 = 1;
3825 + if(Nvaudio_verifyac3(nvstream,buffer,count)) {
3826 + printk("Nvsound: VERIFIED AS AC3 STREAM \n");
3827 + Nvfree_reopenStream(nvwavdev,file);
3829 + }*/
3831 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
3832 + if( ppos != &file->f_pos)
3833 + return -ESPIPE;
3834 +#endif
3836 + if(nvstream->mapped)
3837 + return -ENXIO;
3839 + if (!access_ok(VERIFY_READ, buffer, count))
3840 + return -EFAULT;
3842 + //printk("Nvsound: newstream %p buffer %x size %d \n",stream, buffer,count);
3843 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3844 + add_wait_queue(&nvstream->wait,&waitb);
3845 +#endif
3846 + while(sent < count) {
3847 + //copy as much as we caninto the dma buffers
3848 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3849 + set_current_state(TASK_INTERRUPTIBLE);
3850 +#else
3851 + prepare_to_wait(&nvstream->wait,&waitb,TASK_INTERRUPTIBLE);
3852 +#endif
3853 + xfer = Nvfill_mem(card,nvstream,buffer+sent,(count-sent));
3854 + sent += xfer;
3855 + nvstream->total_sent += xfer;
3857 + if(nvstream->pre_roll) { // stream not started app will call the start
3858 + if(sent < count){
3859 + sent = (sent)? (ssize_t) sent : -EAGAIN;
3860 + goto dacdone;
3861 + }else {
3862 + break;
3865 + if(nvstream->enable) { // stream already started
3866 + if(sent < count) {
3867 + if(file->f_flags & O_NONBLOCK) {
3868 + sent = (sent) ? (ssize_t)sent: -EAGAIN;
3869 + goto dacdone;
3872 + //interruptible_sleep_on(&nvstream->wait);
3873 + schedule_timeout(15);
3874 + if(signal_pending(current)) {
3875 + //printk("KILL THE APPS \n");
3876 + sent = (sent)? (ssize_t)sent : -ERESTARTSYS;
3877 + goto dacdone;
3879 + continue;
3882 + } else {
3883 + // stream not started yet - start if enough data or DSP_SYNC will be sent to start
3884 + if(nvstream->total_sent >= (2 * nvstream->frag_size)) {
3885 + spin_lock_irqsave(&card->play_lock, flags);
3886 + Nv_start((void*)nvstream->wavestream);
3887 + nvstream->enable = TRUE;
3888 + spin_unlock_irqrestore(&card->play_lock, flags);
3889 + }else {
3890 + if(sent < count){
3891 + sent= (sent)? (ssize_t) sent : -EAGAIN;
3898 +dacdone:
3899 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3900 + set_current_state(TASK_RUNNING);
3901 + remove_wait_queue(&nvstream->wait,&waitb);
3902 +#else
3903 + finish_wait(&nvstream->wait,&waitb);
3904 +#endif
3906 + return sent;
3908 +////////////////////////////////////////////////////////////////////////
3909 +// Function to poll the hw status
3910 +////////////////////////////////////////////////////////////////////////
3911 +static unsigned int Nvaudio_poll(struct file *file, struct poll_table_struct *wait)
3913 + unsigned int mask = 0;
3914 + unsigned long flags = 0;
3915 + int i = 0;
3916 + Nvaudio_wavedev *nvwavdev = NULL;
3917 + Nvaudio_card *card = (Nvaudio_card *)file->private_data;
3918 + //printk("Nvaudio: Nvaudio_poll \n");
3919 + nvwavdev = Nvfind_wave_device(card,file);
3920 + if(!nvwavdev) {
3921 + printk("Nvsound: Unable to find any wave device \n");
3922 + return -ENXIO;
3925 + if(file->f_mode& FMODE_WRITE) {
3926 + poll_wait(file,&nvwavdev->playback_stream.wait,wait);
3929 + if(file->f_mode& FMODE_READ) {
3930 + poll_wait(file,&nvwavdev->record_stream.wait,wait);
3933 + if (file->f_mode & FMODE_READ) {
3934 + spin_lock_irqsave(&card->rec_lock, flags);
3935 + for (i=0; i < nvwavdev->record_stream.num_frags; i++) {
3936 + if (nvwavdev->record_stream.buf[i].count > 0) {
3937 + mask |= POLLIN | POLLRDNORM;
3938 + break;
3941 + spin_unlock_irqrestore(&card->rec_lock, flags);
3944 + if (file->f_mode & FMODE_WRITE) {
3945 + spin_lock_irqsave(&card->play_lock, flags);
3946 + for (i=0; i < nvwavdev->playback_stream.num_frags; i++) {
3947 + if (nvwavdev->playback_stream.buf[i].count < nvwavdev->playback_stream.frag_size) {
3948 + mask |= POLLOUT | POLLWRNORM;
3949 + break;
3952 + spin_unlock_irqrestore(&card->play_lock, flags);
3955 + return mask;
3958 +////////////////////////////////////////////////////////////////////////
3959 +// Function to do mmap ioctls
3960 +////////////////////////////////////////////////////////////////////////
3961 +static int Nvaudio_mmap(struct file *file, struct vm_area_struct *vma)
3963 + Nvaudio_wavedev *nvwavdev = NULL;
3964 + Nvaudio_stream *nvstream = NULL;
3965 + unsigned long size = 0, *phyArray = 0;
3966 + int pagecount = 0, pages = 0;
3967 + Nvaudio_card * card = file->private_data;
3969 + //printk("Nvsound: Nvaudio_mmap \n");
3971 + nvwavdev = Nvfind_wave_device(card,file);
3972 + if(!nvwavdev) {
3973 + printk("Nvsound: Unable to find any wave device \n");
3974 + return -ENXIO;
3977 + size = vma->vm_end - vma->vm_start;
3979 + //
3980 + // check whether it is from our private allocation
3981 + //
3982 + if(Nv_IsMmValid()){
3983 + //printk("Nvsound: mmap([0x%p-0x%p] off=0x%lx)\n",vma->vm_start,vma->vm_end,
3984 + // NV_VMA_OFFSET(vma));
3985 + pagecount = size >> PAGE_SHIFT;
3986 + pages = pagecount;
3988 + if(Nv_FindMmEntry((void *)NV_VMA_OFFSET(vma), (void**) &phyArray,pagecount)) {
3989 + // find in the list - remap it based on page count
3990 + unsigned long start = 0, phyAddr = 0;
3991 + start = vma->vm_start;
3992 +#if defined (__x86_64__)
3993 + phyAddr = NV_VMA_OFFSET(vma);
3994 +#endif
3995 + while(pagecount--) {
3996 +#if defined (__i386__)
3997 + if(phyArray)
3998 + phyAddr = *phyArray;
4000 + if(phyAddr == 0) return -EINVAL;
4001 +#endif
4002 + if (NV_REMAP_PAGE_RANGE(start, phyAddr, PAGE_SIZE, vma->vm_page_prot)) {
4003 + return -EAGAIN;
4005 + start += PAGE_SIZE;
4006 +#if defined (__x86_64__)
4007 + phyAddr += PAGE_SIZE; // using this as we did contiguous memory allocation
4008 +#else
4009 + phyArray++;
4010 +#endif
4011 + }
4012 + // prevent the swapper from swapping it out
4013 + // mark the memory i/o so the buffers aren't dumped on core dumps
4014 + vma->vm_flags |= (VM_IO | VM_LOCKED);
4015 + vma->vm_file = file;
4017 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10))
4018 + if (vma->vm_flags & VM_LOCKED)
4019 + current->mm->locked_vm += pages;
4020 +#endif
4022 + return 0;
4026 + // recheck this how important is this
4027 + if(vma->vm_pgoff != 0)
4028 + return -EINVAL;
4030 + lock_kernel();
4032 + if (vma->vm_flags & VM_WRITE) {
4033 + nvstream = &nvwavdev->playback_stream;
4034 + if (!nvstream->wavestream || nvstream->enable || nvstream->mapped) {
4035 + unlock_kernel();
4036 + return -EINVAL;
4038 + if (size > (PAGE_SIZE << nvstream->buf_order)) {
4039 + unlock_kernel();
4040 + return -EINVAL;
4042 + if (NV_REMAP_PAGE_RANGE(vma->vm_start, virt_to_phys(nvstream->vir_dmabuf), size, vma->vm_page_prot)) {
4043 + unlock_kernel();
4044 + return -EAGAIN;
4046 + nvstream->mapped = TRUE;
4047 + unlock_kernel(); /* so we don't map twice if someone opens rw */
4048 + return 0;
4051 + if (vma->vm_flags & VM_READ) {
4052 + nvstream = &nvwavdev->record_stream;
4053 + if (!nvstream->wavestream || nvstream->enable || nvstream->mapped) {
4054 + unlock_kernel();
4055 + return -EINVAL;
4057 + if (size > (PAGE_SIZE << nvstream->buf_order)) {
4058 + unlock_kernel();
4059 + return -EINVAL;
4061 + if (NV_REMAP_PAGE_RANGE(vma->vm_start, virt_to_phys(nvstream->vir_dmabuf), size, vma->vm_page_prot)) {
4062 + unlock_kernel();
4063 + return -EAGAIN;
4065 + nvstream->mapped = TRUE;
4067 + unlock_kernel();
4068 + return 0;
4071 +////////////////////////////////////////////////////////////////////////
4072 +// Function to do fill the memory appropriately for recording data
4073 +////////////////////////////////////////////////////////////////////////
4074 +static unsigned long Nvget_mem(Nvaudio_card *card, Nvaudio_stream *nvstream, char *mem, unsigned long size)
4076 + unsigned long flags = 0;
4077 + unsigned long received = 0;
4078 + unsigned long count = 0, AmountToCopy = 0;
4079 + int status = 0, i=0;
4080 + mem_buf_t *mb = NULL;
4081 +#if (ENABLE_MONO)
4082 + u16* buffloc = NULL;
4083 + u16 left = 0 , right = 0;
4084 +#endif
4085 + // if not enabled yet add all the buffer to the stream
4086 + if(!nvstream->enable) {
4087 + spin_lock_irqsave(&card->rec_lock,flags);
4088 + for(i=0; i<nvstream->num_frags; i++) {
4089 + nvstream->buf[i].count = nvstream->frag_size;
4090 + nvstream->buf[i].in_use = TRUE;
4091 + status = Nv_passdown((void*)nvstream->wavestream,nvstream->buf[i].page,nvstream->buf[i].count,i,FALSE);
4092 + if(status) { // no more space to fill
4093 + nvstream->buf[i].count = 0;
4094 + nvstream->buf[i].in_use = FALSE;
4095 + break;
4098 + spin_unlock_irqrestore(&card->rec_lock,flags);
4099 + return 0;
4102 + AmountToCopy = size;
4103 + while((received < size) && (!nvstream->buf[nvstream->drain_index].in_use)) {
4104 + mb = (mem_buf_t *) &nvstream->buf[nvstream->drain_index];
4105 + count = AmountToCopy < (nvstream->frag_size - mb->count) ? AmountToCopy : nvstream->frag_size - mb->count;
4107 + if(nvstream->Channels > 1) {
4108 + if(copy_to_user(mem,(u8*)mb->page + mb->count ,count)) {
4109 + break;
4111 + mb->count += count;
4112 + AmountToCopy -= count;
4114 +#if (ENABLE_MONO)
4115 + else {
4116 + count = count >> 1;
4117 + buffloc = (u16 *)mb->page + (mb->count / 2) ;
4118 + for(i = 0; i < (count/2) ; i++) {
4119 + left = *buffloc++;
4120 + mb->count += 2;
4121 + right = *buffloc++;
4122 + mb->count += 2;
4123 + if(copy_to_user(mem,(void*)&left,sizeof(u16))) {
4124 + status = 1;
4125 + break;
4127 + mem += sizeof(u16);
4128 + received += sizeof(u16);
4131 + if(status) break;
4132 + AmountToCopy = ((size - received) << 1);
4134 +#endif
4135 + // once the buffer is copied add the buffer back if possible
4136 + if (mb->count >= nvstream->frag_size) {
4137 + spin_lock_irqsave(&card->rec_lock,flags);
4138 + status = Nv_passdown(nvstream->wavestream,nvstream->buf[nvstream->drain_index].page,nvstream->frag_size,nvstream->drain_index,FALSE);
4139 + spin_unlock_irqrestore(&card->rec_lock,flags);
4140 + if(status == 0) {
4141 + nvstream->buf[nvstream->drain_index].count = nvstream->frag_size;
4142 + nvstream->buf[nvstream->drain_index].xfer = 0;
4143 + nvstream->buf[nvstream->drain_index].in_use = TRUE;
4144 + nvstream->drain_index = (nvstream->drain_index + 1) % nvstream->num_frags;
4148 + if(nvstream->Channels > 1) {
4149 + received += count;
4150 + mem += count;
4153 + return received;
4156 +////////////////////////////////////////////////////////////////////////
4157 +// Function to do fill the memory appropriately for playback data
4158 +////////////////////////////////////////////////////////////////////////
4159 +static unsigned long Nvfill_mem(Nvaudio_card *card, Nvaudio_stream *nvstream, const char *mem, unsigned long size)
4161 + unsigned long flags = 0;
4162 + unsigned long sent = 0;
4163 + unsigned long count;
4164 + int status = 0;
4165 + mem_buf_t *mb = (mem_buf_t *) &nvstream->buf[nvstream->fill_index];
4166 + while ((size > 0) && !mb->in_use) {
4167 + count = size < (nvstream->frag_size - mb->count) ? size : nvstream->frag_size - mb->count;
4168 + if(copy_from_user((u8 *)mb->page + mb->count, mem, count))
4169 + break;
4170 + mb->count += count;
4171 + // Send buffer to the dma engine if full.
4172 + if (mb->count >= nvstream->frag_size) {
4173 + spin_lock_irqsave(&card->play_lock, flags);
4174 + status = Nv_passdown((void*)nvstream->wavestream,mb->page,mb->count,nvstream->fill_index,FALSE);
4175 + if(status) {
4176 + // unable to fill it now
4177 + spin_unlock_irqrestore(&card->play_lock, flags);
4178 + mb->count -= count;
4179 + return sent;
4181 + spin_unlock_irqrestore(&card->play_lock, flags);
4182 + mb->in_use = TRUE;
4183 + mb->xfer = 0;
4184 + nvstream->fill_index = (nvstream->fill_index + 1) % nvstream->num_frags;
4185 + mb = (mem_buf_t *)&nvstream->buf[nvstream->fill_index];
4187 + size -= count;
4188 + sent += count;
4189 + mem += count;
4191 + return sent;
4193 +#if(PRINT_IOCTL)
4194 +////////////////////////////////////////////////////////////////////////
4195 +// Function to print which ioctl get called
4196 +////////////////////////////////////////////////////////////////////////
4197 +static void Nvprint_ioctl(unsigned int cmd, unsigned long arg)
4199 + unsigned int args = 0;
4200 + get_user(args, (int *)arg);
4201 + switch(cmd){
4202 + case OSS_GETVERSION:
4203 + printk("Nvsound: OSS_GETVERSION \n");
4204 + break;
4205 + case SNDCTL_DSP_RESET:
4206 + printk("Nvsound: SNDCTL_DSP_RESET \n");
4207 + break;
4208 + case SNDCTL_DSP_SYNC:
4209 + printk("Nvsound: SNDCTL_DSP_SYNC \n");
4210 + break;
4211 + case SNDCTL_DSP_SPEED: /* set smaple rate */
4212 + printk("Nvsound: SNDCTL_DSP_SPEED with Arg %d\n", args);
4213 + break;
4214 + case SNDCTL_DSP_STEREO:
4215 + printk("Nvsound: SNDCTL_DSP_STEREO with Arg %d\n", args);
4216 + break;
4217 + case SNDCTL_DSP_GETBLKSIZE:
4218 + printk("Nvsound: SNDCTL_DSP_GETBLKSIZE \n");
4219 + break;
4220 + case SNDCTL_DSP_GETFMTS:
4221 + printk("Nvsound: SNDCTL_DSP_GETFMTS \n");
4222 + break;
4223 + case SNDCTL_DSP_SETFMT:
4224 + printk("Nvsound: SNDCTL_DSP_SETFMT with Arg %d\n", args);
4225 + break;
4226 + case SNDCTL_DSP_CHANNELS:
4227 + printk("Nvsound: SNDCTL_DSP_CHANNELS with Arg %d\n", args);
4228 + break;
4229 + case SNDCTL_DSP_POST:
4230 + printk("Nvsound: SNDCTL_DSP_POST \n");
4231 + break;
4232 + case SNDCTL_DSP_SUBDIVIDE:
4233 + printk("Nvsound: SNDCTL_DSP_SUBDIVIDE with Arg %d\n", args);
4234 + break;
4235 + case SNDCTL_DSP_SETFRAGMENT:
4236 + printk("Nvsound: SNDCTL_DSP_SETFRAGMENT with Arg %d\n", args);
4237 + break;
4238 + case SNDCTL_DSP_GETOSPACE:
4239 + printk("Nvsound: SNDCTL_DSP_GETOSPACE \n");
4240 + break;
4241 + case SNDCTL_DSP_GETOPTR:
4242 + printk("Nvsound: SNDCTL_DSP_GETOPTR \n");
4243 + break;
4244 + case SNDCTL_DSP_GETISPACE:
4245 + printk("Nvsound: SNDCTL_DSP_GETISPACE \n");
4246 + break;
4247 + case SNDCTL_DSP_GETIPTR:
4248 + printk("Nvsound: SNDCTL_DSP_GETIPTR \n");
4249 + break;
4250 + case SNDCTL_DSP_NONBLOCK:
4251 + printk("Nvsound: SNDCTL_DSP_NONBLOCK \n");
4252 + break;
4253 + case SNDCTL_DSP_GETCAPS:
4254 + printk("Nvsound: SNDCTL_DSP_GETCAPS \n");
4255 + break;
4256 + case SNDCTL_DSP_GETTRIGGER:
4257 + printk("Nvsound: SNDCTL_DSP_GETTRIGGER \n");
4258 + break;
4259 + case SNDCTL_DSP_SETTRIGGER:
4260 + printk("Nvsound: SNDCTL_DSP_SETTRIGGER with Arg %d\n", args);
4261 + break;
4262 + case SNDCTL_DSP_SETDUPLEX:
4263 + printk("Nvsound: SNDCTL_DSP_SETDUPLEX \n");
4264 + break;
4265 + case SNDCTL_DSP_GETODELAY:
4266 + printk("Nvsound: SNDCTL_DSP_GETODELAY \n");
4267 + break;
4268 + case SOUND_PCM_READ_RATE:
4269 + printk("Nvsound: SOUND_PCM_READ_RATE \n");
4270 + break;
4271 + case SOUND_PCM_READ_CHANNELS:
4272 + printk("Nvsound: SOUND_PCM_READ_CHANNELS \n");
4273 + break;
4274 + case SOUND_PCM_READ_BITS:
4275 + printk("Nvsound: SOUND_PCM_READ_BITS \n");
4276 + break;
4277 + case SNDCTL_DSP_SETSPDIF:
4278 + printk("Nvsound: SNDCTL_DSP_SETSPDIF \n");
4279 + break;
4280 + case SNDCTL_DSP_GETSPDIF:
4281 + printk("Nvsound: SNDCTL_DSP_GETSPDIF \n");
4282 + break;
4283 + case SNDCTL_DSP_GETCHANNELMASK:
4284 + printk("Nvsound: SNDCTL_DSP_GETCHANNELMASK \n");
4285 + break;
4286 + case SNDCTL_DSP_BIND_CHANNEL:
4287 + printk("Nvsound: SNDCTL_DSP_BIND_CHANNEL \n");
4288 + break;
4289 + default:
4290 + printk("Nvsound: DEFAULT \n");
4294 +#endif
4296 +////////////////////////////////////////////////////////////////////////
4297 +// OSS ioctls are supported in this function
4298 +////////////////////////////////////////////////////////////////////////
4299 +static int Nvaudio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
4301 + int val = 0, i = 0, status = 0;
4302 + unsigned long flags = 0;
4303 + audio_buf_info abinfo;
4304 + int nfrags =0, fragsize =0;
4305 + count_info cinfo;
4306 + Nvaudio_stream* nvstream = NULL;
4307 + Nvaudio_wavedev* nvwavdev = NULL;
4308 + Nvaudio_card *card = (Nvaudio_card *)file->private_data;
4309 +#if(PRINT_IOCTL)
4310 + Nvprint_ioctl(cmd,arg);
4311 +#endif
4313 + nvwavdev = Nvfind_wave_device(card,file);
4314 + if(!nvwavdev) {
4315 + printk("Nvsound: Unable to find any wave device \n");
4316 + return -ENXIO;
4319 + switch(cmd){
4320 + case OSS_GETVERSION:
4321 + return put_user(SOUND_VERSION, (int *)arg);
4323 + case SNDCTL_DSP_RESET:
4325 + Nvstop_wave(card,&(nvwavdev->playback_stream),PLAY_STREAM);
4326 + Nvstop_wave(card,&(nvwavdev->record_stream),REC_STREAM);
4327 + return 0;
4328 + }
4330 + case SNDCTL_DSP_SYNC:
4332 + if(file->f_flags & O_NONBLOCK)
4333 + return 0;
4334 + if(nvwavdev->playback_stream.wavestream) {
4335 + drain_dac(card,nvwavdev,(file->f_flags & O_NONBLOCK));
4336 + Nvstop_wave(card,&(nvwavdev->playback_stream),PLAY_STREAM);
4338 + if(nvwavdev->record_stream.wavestream) {
4339 + Nvstop_wave(card,&(nvwavdev->record_stream),REC_STREAM);
4341 + return 0;
4344 + case SNDCTL_DSP_SPEED: /* set sample rate */
4345 + if (get_user(val, (int *)arg))
4346 + return -EFAULT;
4348 + if(file->f_mode & FMODE_READ){
4349 + nvwavdev->record_stream.fmt.dwSampleRate = val;
4350 + nvstream = &nvwavdev->record_stream;
4351 + if(nvstream->wavestream) {
4352 + status = Nv_SetFormat((void*)nvstream->wavestream,&nvstream->fmt,SETSAMPLERATE);
4353 + if(status) {
4354 + printk("Nvsound: Unable to change the Record SampleRate %d, set back to 48000 \n",val);
4355 + if(!(file->f_mode & FMODE_WRITE)) val = DEFAULT_SAMPLERATE;
4356 + nvwavdev->record_stream.fmt.dwSampleRate = DEFAULT_SAMPLERATE;
4361 + if(file->f_mode & FMODE_WRITE) {
4362 + nvwavdev->playback_stream.fmt.dwSampleRate = val;
4363 + nvstream = &nvwavdev->playback_stream;
4364 + status = Nv_SetFormat((void*)nvstream->wavestream,&nvstream->fmt,SETSAMPLERATE);
4365 + if(status) {
4366 + printk("Nvsound: Unable to change the Playback SampleRate %d, set back to 48000 \n",val);
4367 + val = DEFAULT_SAMPLERATE;
4368 + nvwavdev->playback_stream.fmt.dwSampleRate = DEFAULT_SAMPLERATE;
4372 + return put_user(val, (int *)arg);
4374 + case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
4375 + if (get_user(val, (int *) arg))
4376 + return -EFAULT;
4377 + if(file->f_mode & FMODE_WRITE){
4378 + nvstream = &nvwavdev->playback_stream;
4379 + nvstream->fmt.wChannels = (val ? 2 : 1);
4380 + status = Nv_SetFormat((void*)nvstream->wavestream,&nvstream->fmt,SETCHANNELS);
4381 + if(status){
4382 + printk("Nvsound: Unable to set Mono, set back to Stereo \n");
4383 + nvstream->fmt.wChannels = 2;
4384 + val = 1 ; // set back to stereo
4387 + if(file->f_mode & FMODE_READ) {
4388 +#if (ENABLE_MONO)
4389 + if(val == 0) nvwavdev->record_stream.Channels = 1;
4390 +#endif
4392 + return put_user(val, (int *)arg);
4394 + case SNDCTL_DSP_GETBLKSIZE:
4395 + val = nvwavdev->playback_stream.frag_size;
4396 +#if(PRINT_IOCTL)
4397 + printk(" Get BlockSize %d \n", val);
4398 +#endif
4399 + return put_user(val,(int *)arg);
4401 + case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
4403 + if(file->f_mode & FMODE_READ){
4404 + val = AFMT_S16_LE;
4406 + if(file->f_mode & FMODE_WRITE){
4407 + val = AFMT_S16_LE | AFMT_U8 | AFMT_AC3;
4410 + if((file->f_mode & FMODE_READ) && (file->f_mode & FMODE_WRITE)) {
4411 + val = AFMT_S16_LE;
4413 +#if(PRINT_IOCTL)
4414 + printk(" Get Format as %d \n", val);
4415 +#endif
4416 + return put_user(val, (int *) arg);
4420 + case SNDCTL_DSP_SETFMT: /* Select sample format */
4422 + if(get_user(val,(int *)arg))
4423 + return -EFAULT;
4424 + if(val != AFMT_QUERY) {
4426 + if(file->f_mode & FMODE_READ){
4427 + if(!(file->f_mode & FMODE_WRITE)) val = AFMT_S16_LE;
4429 + if(file->f_mode & FMODE_WRITE){
4430 + if( (card->ac3_in_use) && (val == AFMT_AC3)) {
4431 + // reset the value as AFMT_S16_LE
4432 + val = AFMT_S16_LE;
4433 + }else {
4434 + // HACK ADDED FOR SPDIF - First verify the opened stream is of AFMT_AC3 format
4435 + // If NOT KILL the opened stream and open a new stream with SpdifOut
4436 + if(nvwavdev->playback_stream.wavestream) {
4437 + nvstream = &nvwavdev->playback_stream;
4438 + if( val == AFMT_AC3) {
4439 + if(nvstream->fmt.wformat != AFMT_AC3) {
4440 + nvstream->fmt.wformat = val;
4441 + Nvfree_reopenStream(nvwavdev,file);
4442 + nvstream->verifyac3 = 1;
4443 + nvstream->fmt.wBitsPerSample = 16;
4446 + else if( val == AFMT_S16_LE) {
4447 + nvstream->fmt.wBitsPerSample = 16;
4449 + else if ( val == AFMT_U8) {
4450 + nvstream->fmt.wBitsPerSample = 8;
4452 + nvstream->fmt.wformat = val;
4453 + //printk("Nvsound: Set format as %x \n", val);
4454 + Nv_SetFormat((void*)nvstream->wavestream,&nvstream->fmt,SETFORMAT);
4459 + return put_user(val,(int*)arg);
4462 + case SNDCTL_DSP_CHANNELS:
4464 + if(get_user(val,(int *)arg))
4465 + return -EFAULT;
4466 + if(file->f_mode & FMODE_READ){
4467 +#if(ENABLE_MONO)
4468 + nvstream = &nvwavdev->record_stream;
4469 + if(val == 1) nvstream->Channels = val;
4470 +#endif
4472 + if(file->f_mode & FMODE_WRITE){
4473 + if(nvwavdev->playback_stream.wavestream) {
4474 + nvstream = &nvwavdev->playback_stream;
4475 + nvstream->fmt.wChannels = val;
4476 + spin_lock_irqsave(&card->play_lock,flags);
4477 + status = Nv_SetFormat((void*)nvstream->wavestream,&nvstream->fmt,SETCHANNELS);
4478 + spin_unlock_irqrestore(&card->play_lock,flags);
4479 + if(status){
4480 + printk("Nvsound: Unable to change the Channel, set back to Stereo \n");
4481 + val = 2 ; // set back to stereo
4482 + nvstream->fmt.wChannels = val;
4486 + return put_user(val,(int*) arg);
4489 + case SNDCTL_DSP_POST:
4491 + if(!nvwavdev->playback_stream.wavestream)
4492 + return -EINVAL;
4493 + drain_dac(card,nvwavdev,(file->f_flags & O_NONBLOCK));
4494 + Nvstop_wave(card,&(nvwavdev->playback_stream),PLAY_STREAM);
4495 + return 0;
4498 + case SNDCTL_DSP_SUBDIVIDE:
4499 + if (get_user(val, (int *)arg))
4500 + return -EFAULT;
4501 + return 0;
4503 + case SNDCTL_DSP_SETFRAGMENT:
4504 + if (get_user(val, (int *) arg))
4505 + return -EFAULT;
4506 + nfrags = (val >> 16) & 0xffff;
4507 + fragsize = 1 << (val & 0xffff);
4508 + //printk(" nfrags %d fragsize %d \n", nfrags,fragsize);
4509 + nvstream = &nvwavdev->playback_stream;
4510 + if(nvstream) {
4511 + if(fragsize > nvstream->frag_size){
4512 + nfrags = nfrags * (fragsize / nvstream->frag_size);
4513 + fragsize = nvstream->frag_size;
4514 + }else if(fragsize < (nvstream->frag_size / 4)){
4515 + nfrags = nfrags * 4;
4516 + fragsize = nvstream->frag_size / 4;
4519 + if(nfrags > NVBUFFER_FRAGMENTS) nfrags = NVBUFFER_FRAGMENTS;
4521 + val = fragsize * nfrags;
4522 + while (val > (NVMAX_FRAGSIZE * NVMAX_FRAGS)){
4523 + nfrags = nfrags >> 1;
4524 + val = fragsize * nfrags;
4527 + nvstream->num_frags = nfrags;
4528 + nvstream->frag_size = fragsize;
4531 + nvstream = &nvwavdev->record_stream;
4532 + if(nvstream) {
4533 + nvstream->num_frags = nfrags;
4534 + nvstream->frag_size = fragsize;
4536 + //printk(" nfrags %d fragsize %d \n", nfrags,fragsize);
4537 + status = 0;
4538 + return status;
4540 + case SNDCTL_DSP_GETOSPACE:
4542 + if(!nvwavdev->playback_stream.wavestream)
4543 + return -EINVAL;
4544 + nvstream = &nvwavdev->playback_stream;
4545 + abinfo.fragsize = nvstream->frag_size;
4546 + abinfo.fragstotal = nvstream->num_frags;
4547 + abinfo.bytes = 0;
4548 + abinfo.fragments = 0;
4549 + spin_lock_irqsave(&card->play_lock,flags);
4550 + for(i = 0; i < nvstream->num_frags; i++) {
4551 + if(!nvstream->buf[i].in_use) {
4552 + abinfo.bytes += (nvstream->frag_size - nvstream->buf[i].count);
4553 + if (nvstream->buf[i].count == 0)
4554 + ++abinfo.fragments;
4555 + }
4557 + spin_unlock_irqrestore(&card->play_lock,flags);
4558 +#if(PRINT_IOCTL)
4559 + printk(" Bytes %d frags %d \n", abinfo.bytes, abinfo.fragments);
4560 +#endif
4561 + return copy_to_user((void*)arg,&abinfo,sizeof(abinfo)) ? -EFAULT: 0;
4564 + case SNDCTL_DSP_GETOPTR:
4566 + nvstream = &nvwavdev->playback_stream;
4567 + cinfo.blocks = nvstream->total_played / nvstream->frag_size;
4568 + cinfo.bytes = nvstream->total_played;
4569 + cinfo.ptr = (nvstream->frag_size * nvstream->drain_index) + nvstream->buf[nvstream->drain_index].xfer;
4570 +#if(PRINT_IOCTL)
4571 + printk(" Current ptr %d totalplayed %d blocks avail %d \n", cinfo.ptr,cinfo.bytes,cinfo.blocks);
4572 +#endif
4573 + return copy_to_user((void*)arg, &cinfo, sizeof(cinfo));
4576 + case SNDCTL_DSP_GETISPACE:
4578 + if(!nvwavdev->record_stream.wavestream)
4579 + return -EINVAL;
4580 + nvstream = &nvwavdev->record_stream;
4581 + abinfo.fragsize = nvstream->frag_size;
4582 + abinfo.fragstotal = nvstream->num_frags;
4583 + abinfo.bytes = 0;
4584 + abinfo.fragments = 0;
4585 + spin_lock_irqsave(&card->rec_lock,flags);
4586 + for(i=0; i < nvstream->num_frags; i++) {
4587 + if(!nvstream->buf[i].in_use){
4588 + abinfo.bytes += (nvstream->frag_size - nvstream->buf[i].count);
4589 + if(nvstream->buf[i].count == 0)
4590 + ++abinfo.fragments;
4593 + spin_unlock_irqrestore(&card->rec_lock,flags);
4594 + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
4595 + }
4597 + case SNDCTL_DSP_GETIPTR:
4599 + nvstream = &nvwavdev->record_stream;
4600 + cinfo.bytes = nvstream->total_played;
4601 + cinfo.blocks = nvstream->total_played / nvstream->frag_size;
4602 + cinfo.ptr = (nvstream->frag_size * nvstream->fill_index) + nvstream->buf[nvstream->fill_index].xfer;
4603 +#if(PRINT_IOCTL)
4604 + printk(" Current ptr %d totalplayed %d blocks avail %d \n", cinfo.ptr,cinfo.bytes,cinfo.blocks);
4605 +#endif
4606 + return copy_to_user((void*)arg, &cinfo, sizeof(cinfo));
4609 + case SNDCTL_DSP_NONBLOCK:
4610 + file->f_flags |= O_NONBLOCK;
4611 + return 0;
4613 + case SNDCTL_DSP_GETCAPS:
4614 + return put_user(DSP_CAP_DUPLEX| DSP_CAP_REALTIME |DSP_CAP_TRIGGER |DSP_CAP_MMAP |DSP_CAP_MULTI, (int *)arg);
4616 + case SNDCTL_DSP_GETTRIGGER:
4618 + val = 0;
4619 + if(nvwavdev->record_stream.wavestream && !nvwavdev->record_stream.pre_roll)
4620 + val |= PCM_ENABLE_INPUT;
4621 + if(nvwavdev->playback_stream.wavestream && !nvwavdev->playback_stream.pre_roll)
4622 + val |= PCM_ENABLE_OUTPUT;
4623 + return put_user(val, (int *)arg);
4626 + case SNDCTL_DSP_SETTRIGGER:
4628 + if(get_user(val,(int *)arg)){
4629 + return -EFAULT;
4632 + if (file->f_mode & FMODE_READ) {
4633 + nvstream = &nvwavdev->record_stream;
4634 + if(val & PCM_ENABLE_INPUT) {
4635 + if (nvstream->wavestream && (nvstream->pre_roll || nvstream->mapped)) {
4636 + spin_lock_irqsave(&card->rec_lock, flags);
4638 + for (i = 0; i < nvstream->num_frags; i++){
4639 + nvstream->buf[i].count = nvstream->frag_size;
4640 + nvstream->buf[i].in_use = TRUE;
4641 + memset(nvstream->buf[i].page, (nvstream->fmt.wformat == AFMT_S16_LE) ? 0 : 0x80, nvstream->frag_size);
4642 + Nv_passdown(nvstream->wavestream, nvstream->buf[i].page, nvstream->frag_size,i,FALSE);
4645 + if (nvstream->mapped && !nvstream->mapped_setup) {
4646 + nvstream->mapped_setup = TRUE;
4649 + Nv_start(nvstream->wavestream);
4650 + nvstream->enable = TRUE;
4651 + nvstream->pre_roll = FALSE;
4652 + spin_unlock_irqrestore(&card->rec_lock, flags);
4654 + } else if (nvstream->wavestream) {
4655 + if(nvstream->mapped && nvstream->mapped_setup) {
4656 + spin_lock_irqsave(&card->rec_lock, flags);
4657 + Nv_stop(nvstream->wavestream);
4658 + spin_unlock_irqrestore(&card->rec_lock, flags);
4659 + }else{
4660 + Nvstop_wave(card,nvstream,REC_STREAM);
4662 + nvstream->pre_roll = TRUE;
4666 + if(file->f_mode & FMODE_WRITE) {
4667 + nvstream = &nvwavdev->playback_stream;
4668 + if(val & PCM_ENABLE_OUTPUT) {
4669 + if(nvstream->wavestream && (nvstream->mapped || nvstream->pre_roll)){
4670 + spin_lock_irqsave(&card->play_lock,flags);
4671 + for (i = 0; i < nvstream->num_frags; i++) {
4672 + nvstream->buf[i].count = nvstream->frag_size;
4673 + nvstream->buf[i].in_use = TRUE;
4674 + memset(nvstream->buf[i].page, (nvstream->fmt.wformat == AFMT_S16_LE) ? 0 : 0x80, nvstream->frag_size);
4675 + Nv_passdown(nvstream->wavestream, nvstream->buf[i].page, nvstream->frag_size,i,FALSE);
4677 + if(nvstream->mapped && !nvstream->mapped_setup) {
4678 + nvstream->mapped_setup = TRUE;
4680 + Nv_start(nvstream->wavestream);
4681 + nvstream->enable = TRUE;
4682 + nvstream->pre_roll = FALSE;
4683 + spin_unlock_irqrestore(&card->play_lock,flags);
4685 + }else if(nvstream->wavestream) {
4686 + if(nvstream->mapped && nvstream->mapped_setup){
4687 + spin_lock_irqsave(&card->play_lock,flags);
4688 + Nv_stop(nvstream->wavestream);
4689 + spin_unlock_irqrestore(&card->play_lock,flags);
4690 + }else{
4691 + Nvstop_wave(card,nvstream,PLAY_STREAM);
4693 + nvstream->pre_roll = TRUE;
4697 + return 0;
4700 + case SNDCTL_DSP_SETDUPLEX:
4701 + return 0;
4703 + case SNDCTL_DSP_GETODELAY:
4705 + val = 0;
4706 + nvstream = &nvwavdev->playback_stream;
4707 + for(i=0; i < nvstream->num_frags; i++) {
4708 + if(nvstream->buf[i].in_use)
4709 + val += (nvstream->buf[i].count - nvstream->buf[i].xfer);
4712 + #if(PRINT_IOCTL)
4713 + printk(" DelayBytes %d \n", val);
4714 + #endif
4716 + return put_user(val,(int *)arg);
4719 + case SOUND_PCM_READ_RATE:
4721 + val = 0;
4722 + if (file->f_mode & FMODE_READ) {
4723 + nvstream = &nvwavdev->record_stream;
4724 + val = nvstream->fmt.dwSampleRate;
4727 + if(file->f_mode & FMODE_WRITE) {
4728 + nvstream = &nvwavdev->playback_stream;
4729 + val = nvstream->fmt.dwSampleRate;
4732 + return put_user(val,(int *) arg);
4734 + case SOUND_PCM_READ_BITS:
4736 + val = 0;
4737 + if (file->f_mode & FMODE_READ) {
4738 + nvstream = &nvwavdev->record_stream;
4739 + val = nvstream->fmt.wBitsPerSample;
4742 + if(file->f_mode & FMODE_WRITE) {
4743 + nvstream = &nvwavdev->playback_stream;
4744 + val = nvstream->fmt.wBitsPerSample;
4747 + return put_user(val,(int *) arg);
4750 + case SOUND_PCM_READ_CHANNELS:
4752 + val = 0;
4753 + if (file->f_mode & FMODE_READ) {
4754 + nvstream = &nvwavdev->record_stream;
4755 + val = nvstream->fmt.wChannels;
4758 + if(file->f_mode & FMODE_WRITE) {
4759 + nvstream = &nvwavdev->playback_stream;
4760 + val = nvstream->fmt.wChannels;
4763 + return put_user(val,(int *) arg);
4766 + case SNDCTL_DSP_GETCHANNELMASK:
4767 + case SNDCTL_DSP_BIND_CHANNEL:
4768 + return -EINVAL;
4769 + default:
4770 + return Nvaudio_private_ioctl(card,file,cmd,arg);
4772 + return 0;
4775 +////////////////////////////////////////////////////////////////////////
4776 +// OSS /dev/mixer file operation methods
4777 +////////////////////////////////////////////////////////////////////////
4778 +static int Nvaudio_open_mixdev(struct inode *inode, struct file *file)
4780 + int minor = MINOR(inode->i_rdev);
4781 + // as we support only one card now
4782 + Nvaudio_card *card = devs;
4783 + //printk("Nvsound: Nvaudio_open_mixdev %p \n", card);
4784 + if(!card) return -ENODEV;
4785 + if(card->dev_mixer == minor){
4786 + file->private_data = devs;
4787 + return 0;
4789 + return -ENODEV;
4792 +static struct file_operations Nv_mixer_fops = {
4793 + owner: THIS_MODULE,
4794 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
4795 + llseek: no_llseek,
4796 +#endif
4797 + ioctl: Nvaudio_ioctl_mixdev,
4798 + open: Nvaudio_open_mixdev,
4801 +////////////////////////////////////////////////////////////////////////
4802 +// Function to support the open calls
4803 +// Suppose to call multiple playback streams
4804 +// Support only one record stream
4805 +// Fullduplex supported.
4806 +// If all stream are open just schedule a wait or fail the call
4807 +////////////////////////////////////////////////////////////////////////
4808 +static int Nvaudio_open(struct inode *inode, struct file *file)
4810 + int status = 0;
4811 + int minor_num = DEVMINOR(inode->i_rdev);
4812 + int dev_type = DEVICE_TYPE(minor_num);
4814 + //printk("Open device with file %p \n", (void*)file);
4815 + // need to add a function to find the device when we support multiple cards
4816 + Nvaudio_card *card = devs;
4817 + if(card) {
4818 + status = Nvadd_wave_device(card, file, dev_type);
4819 + if(status) {
4820 + printk("Nvsound: Unable to allocate the wave device \n");
4821 + return status;
4824 + file->private_data = (void *) card;
4825 + return 0;
4828 +////////////////////////////////////////////////////////////////////////
4829 +// Function to stop the running wave
4830 +////////////////////////////////////////////////////////////////////////
4831 +static void Nvstop_wave(Nvaudio_card *card, Nvaudio_stream *nvstream, int type)
4833 + int i;
4834 + unsigned long flags = 0;
4835 + if (nvstream->wavestream) {
4836 + if(type == PLAY_STREAM)
4837 + spin_lock_irqsave(&card->play_lock, flags);
4838 + else
4839 + spin_lock_irqsave(&card->rec_lock, flags);
4840 + Nv_stop(nvstream->wavestream);
4842 + if(type == PLAY_STREAM)
4843 + spin_unlock_irqrestore(&card->play_lock, flags);
4844 + else
4845 + spin_unlock_irqrestore(&card->rec_lock, flags);
4848 + nvstream->enable = nvstream->pre_roll = FALSE;
4849 + nvstream->total_played = nvstream->total_sent = 0;
4850 + nvstream->fill_index = nvstream->drain_index = 0;
4851 + //nvstream->verifyac3 = 0;
4852 + nvstream->lastposition = 0;
4853 + for (i = 0; i < nvstream->num_frags; i++) {
4854 + nvstream->buf[i].count = nvstream->buf[i].xfer = 0;
4855 + nvstream->buf[i].in_use = FALSE;
4858 +////////////////////////////////////////////////////////////////////////
4859 +// Function to support the release/close calls
4860 +////////////////////////////////////////////////////////////////////////
4861 +static int Nvaudio_release(struct inode *inode, struct file *file)
4863 + Nvaudio_wavedev *nvwavdev = NULL;
4864 + Nvaudio_card *card = (Nvaudio_card *)file->private_data;
4865 + //printk("Nvsound: Nvaudio_release with fileptr %p \n", file);
4867 + nvwavdev = Nvfind_wave_device(card,file);
4868 + if(!nvwavdev) {
4869 + printk("Nvsound: Unable to find any wave device \n");
4870 + return -ENXIO;
4872 + lock_kernel();
4874 + if(nvwavdev->playback_stream.wavestream){
4875 + drain_dac(card,nvwavdev,(file->f_flags & O_NONBLOCK));
4877 + if(nvwavdev->record_stream.wavestream){
4878 + card->rec_in_use = FALSE;
4881 + //if(nvwavdev->playback_stream.fmt.wformat == AFMT_AC3) card->ac3_in_use = 0;
4882 + Nvstop_wave(card,&(nvwavdev->playback_stream),PLAY_STREAM);
4883 + Nvstop_wave(card,&(nvwavdev->record_stream),REC_STREAM);
4884 + Nv_VerifyFilePtr((void*)file);
4885 + Nvremove_wave_device(card,nvwavdev);
4886 + unlock_kernel();
4887 + return 0;
4890 +////////////////////////////////////////////////////////////////////////
4891 +// Function to support the release/close calls
4892 +////////////////////////////////////////////////////////////////////////
4893 +static int Nvfree_reopenStream(Nvaudio_wavedev *nvwavdev, struct file *file)
4895 + Nvaudio_stream* nvstream = NULL;
4896 + unsigned long flags = 0;
4897 + int status = 0;
4898 + Nvaudio_card *card = (Nvaudio_card *)file->private_data;
4899 + nvstream = &nvwavdev->playback_stream;
4900 + if(nvstream->wavestream){
4901 + drain_dac(card,nvwavdev,(file->f_flags & O_NONBLOCK));
4903 + Nvstop_wave(card,nvstream,PLAY_STREAM);
4904 + //
4905 + // Remove the opened Stream
4906 + //
4907 + if (nvstream->wavestream) {
4908 + spin_lock_irqsave(&card->play_lock, flags);
4909 + Nv_FreeNewstream(nvstream->wavestream);
4910 + spin_unlock_irqrestore(&card->play_lock, flags);
4912 + //
4913 + // Open a new stream with Spdif out pin
4914 + //
4915 + status = Nv_CreateNewstream(&(nvstream->fmt),NVDIRPLAY,&(nvstream->wavestream),card->hwbase->apupresent);
4916 + if(status) {
4917 + printk("Nvsound: Unable to Create a NewStream for apu \n");
4918 + Nvfree_wave_device(card,nvwavdev);
4919 + return -ENOMEM;
4921 + card->ac3_in_use = 1;
4922 + return status;
4925 +static struct file_operations Nvaudio_fops = {
4926 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
4927 + llseek: no_llseek,
4928 +#endif
4929 + owner: THIS_MODULE,
4930 + read: Nvaudio_read,
4931 + write: Nvaudio_write,
4932 + poll: Nvaudio_poll,
4933 + ioctl: Nvaudio_ioctl,
4934 + mmap: Nvaudio_mmap,
4935 + open: Nvaudio_open,
4936 + release: Nvaudio_release,
4939 +////////////////////////////////////////////////////////////////////////
4940 +// NvRelease_Resources
4941 +////////////////////////////////////////////////////////////////////////
4942 +static void NvRelease_Resources(Nvaudio_card *card)
4944 + if(!card || !(card->hwbase)) {
4945 + devs = 0;
4946 + return;
4949 + // release region & irq of apu portion
4950 + if(card->hwbase->apuirq){
4951 + free_irq(card->hwbase->apuirq,card);
4952 + card->hwbase->apuirq = 0;
4954 + // release region & irq of apu portion
4955 + if(card->hwbase->aciirq){
4956 + free_irq(card->hwbase->aciirq,card);
4957 + card->hwbase->aciirq = 0;
4960 + if(card->hwbase->ac97base) {
4961 + release_region (card->hwbase->ac97base, card->hwbase->ac97length);
4962 + card->hwbase->ac97base = 0;
4963 + card->hwbase->ac97length = 0;
4966 + // release the region for aci
4967 + if(card->hwbase->acibase) {
4968 + release_region (card->hwbase->acibase, card->hwbase->acilength);
4969 + card->hwbase->acibase = 0;
4970 + card->hwbase->acilength = 0;
4971 + pci_set_drvdata(card->hwbase->pAci_dev,NULL);
4974 + if(card->hwbase->apubase) {
4975 + release_mem_region(card->hwbase->apubase,card->hwbase->apulength);
4976 + pci_set_drvdata(card->hwbase->pApu_dev, NULL);
4977 + card->hwbase->apubase = 0;
4978 + card->hwbase->apulength = 0;
4981 + // if /dev/mixer is registered - unregister it
4982 + if(card->dev_mixer > -1 ) {
4983 + unregister_sound_mixer(card->dev_mixer);
4984 + printk("KERN_INFO Nvsound: Release DEV MIXER %d \n", card->dev_mixer);
4985 + card->dev_mixer = -1;
4988 + if(card->dev_audio > -1 ){
4989 + unregister_sound_dsp(card->dev_audio);
4990 + card->dev_audio = -1;
4993 + // disable the pci devices - as 2.6.10 shows warning
4994 + /*if(card->hwbase){
4995 + if(card->hwbase->pAci_dev) {
4996 + pci_disable_device(card->hwbase->pAci_dev);
4997 + card->hwbase->pAci_dev = NULL;
4999 + if(card->hwbase->pApu_dev) {
5000 + pci_disable_device(card->hwbase->pApu_dev);
5001 + card->hwbase->pApu_dev = NULL;
5003 + }*/
5006 + if(card->hwbase){
5007 + kfree(card->hwbase);
5008 + card->hwbase = 0;
5011 + // since we support only one device set devs
5013 + memset(card, 0, sizeof(Nvaudio_card));
5015 + kfree(card);
5017 + devs = NULL;
5020 +////////////////////////////////////////////////////////////////////////
5021 +// Nvaudio Apu Init call
5022 +////////////////////////////////////////////////////////////////////////
5023 +static int Nvaudio_apuinit( PNVHWBASE pHwBase)
5025 + if(Nv_CreateApuExec(pHwBase) == 0) return 1;
5026 + else return -1;
5029 +////////////////////////////////////////////////////////////////////////
5030 +// probe module function
5031 +////////////////////////////////////////////////////////////////////////
5032 +static int __devinit Nvaudio_probe(struct pci_dev *ppci_dev, const struct pci_device_id *pci_id)
5034 + int ret = 0;
5036 + if(pci_set_dma_mask(ppci_dev,NVAUDIO_DMA_MASK)) {
5037 + printk(KERN_ERR "Nvsound: Nvaudio doesnot support PCI busmaster \n ");
5038 + return -ENODEV;
5040 + if(pci_enable_device(ppci_dev))
5041 + return -EIO;
5043 + pci_set_master(ppci_dev);
5045 + /* Handle the apu and aci separately */
5046 + if((ppci_dev->device == PCI_DEVICE_ID_NVIDIA_MCP2_CONTROLLER) ||
5047 + (ppci_dev->device == PCI_DEVICE_ID_NVIDIA_MCP1_CONTROLLER)
5048 + ) {
5050 + if(devs == NULL) {
5051 + if((devs = kmalloc(sizeof(Nvaudio_card),GFP_KERNEL)) == NULL) {
5052 + printk(KERN_ERR "Nvsound: apu: out of Memory \n");
5053 + return -ENOMEM;
5056 + memset(devs, 0, sizeof(Nvaudio_card));
5058 + if((devs->hwbase = kmalloc(sizeof(NVHWBASE),GFP_KERNEL)) == NULL) {
5059 + printk(KERN_ERR "Nvsound: apu hwbase: out of Memory \n");
5060 + return -ENOMEM;
5062 + memset(devs->hwbase, 0, sizeof(NVHWBASE));
5063 + spin_lock_init(&devs->play_lock);
5064 + spin_lock_init(&devs->rec_lock);
5065 + spin_lock_init(&devs->list_lock);
5068 + devs->hwbase->apupresent = 1;
5069 + devs->hwbase->apubase = pci_resource_start(ppci_dev,0);
5070 + devs->hwbase->apulength = pci_resource_len(ppci_dev,0);
5071 + devs->hwbase->apuirq = ppci_dev->irq;
5072 + devs->hwbase->pApu_dev = (void *)ppci_dev;
5074 + devs->pci_id = ppci_dev->device;
5075 + devs->drivertype = APU_DRIVER;
5077 + if(request_mem_region(devs->hwbase->apubase, devs->hwbase->apulength, card_names[pci_id->driver_data]) == NULL) {
5078 + printk(KERN_ERR "Nvsound: APU Region In Use \n");
5079 + ret = -EBUSY;
5080 + NvRelease_Resources(devs);
5081 + return ret;
5084 + printk(KERN_INFO "Nvsound: %s Mem 0x%04lx and IRQ %x\n",
5085 + card_names[pci_id->driver_data], devs->hwbase->apubase,devs->hwbase->apuirq);
5088 + if(request_irq(devs->hwbase->apuirq,&Nvapu_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], devs)) {
5089 + printk(KERN_ERR "Nvsound: IRQ in use \n");
5090 + ret = -EBUSY;
5091 + NvRelease_Resources(devs);
5092 + return ret;
5095 + pci_set_drvdata(ppci_dev, devs);
5097 + }else{
5098 + if(devs == NULL) {
5099 + if((devs = kmalloc(sizeof(Nvaudio_card),GFP_KERNEL)) == NULL) {
5100 + printk(KERN_ERR "Nvsound: out of Memory \n");
5101 + return -ENOMEM;
5103 + memset(devs, 0, sizeof(Nvaudio_card));
5105 + if((devs->hwbase = kmalloc(sizeof(NVHWBASE),GFP_KERNEL)) == NULL) {
5106 + printk(KERN_ERR "Nvsound: aci hwbase: out of Memory \n");
5107 + return -ENOMEM;
5109 + memset(devs->hwbase, 0, sizeof(NVHWBASE));
5110 + spin_lock_init(&devs->play_lock);
5111 + spin_lock_init(&devs->rec_lock);
5112 + spin_lock_init(&devs->list_lock);
5114 + devs->hwbase->acipresent = 1;
5115 + devs->hwbase->ac97base = pci_resource_start(ppci_dev,0);
5116 + devs->hwbase->ac97length = pci_resource_len(ppci_dev,0);
5117 + devs->hwbase->acibase = pci_resource_start(ppci_dev,1);
5118 + devs->hwbase->acilength = pci_resource_len(ppci_dev,1);
5119 + devs->hwbase->aciirq = ppci_dev->irq;
5120 + devs->hwbase->pAci_dev = (void *)ppci_dev;
5122 + devs->pci_id = ppci_dev->device;
5123 + devs->drivertype = ACI_DRIVER;
5125 + if(request_region(devs->hwbase->acibase, devs->hwbase->acilength, card_names[pci_id->driver_data]) == NULL) {
5126 + printk(KERN_ERR "Nvsound: ACI Region In Use \n");
5127 + ret = -EBUSY;
5128 + NvRelease_Resources(devs);
5129 + return ret;
5132 + if(request_region(devs->hwbase->ac97base, devs->hwbase->ac97length, card_names[pci_id->driver_data]) == NULL) {
5133 + printk(KERN_ERR "Nvsound: AC97 Region In Use \n");
5134 + ret = -EBUSY;
5135 + NvRelease_Resources(devs);
5136 + return ret;
5139 + printk(KERN_INFO "Nvsound: %s aci 0x%04lx and ac97 0x%04lx, IRQ %x\n",
5140 + card_names[pci_id->driver_data], devs->hwbase->acibase, devs->hwbase->ac97base,
5141 + devs->hwbase->aciirq);
5143 + // register /dev/mixer
5144 + devs->dev_mixer = -1;
5145 + if ((devs->dev_mixer = register_sound_mixer(&Nv_mixer_fops, -1)) < 0) {
5146 + printk(KERN_ERR "Nvsound: couldn't register mixer!\n");
5147 + NvRelease_Resources(devs);
5148 + ret = -EBUSY;
5149 + return ret;
5152 + devs->dev_audio = -1;
5153 + // register the /dev/dsp
5154 + if((devs->dev_audio = register_sound_dsp(&Nvaudio_fops, -1)) < 0 ) {
5155 + NvRelease_Resources(devs);
5156 + ret = -EBUSY;
5157 + return ret;
5160 + if(devs->hwbase->apupresent)
5161 + pci_set_drvdata(ppci_dev,NULL);
5162 + else
5163 + pci_set_drvdata(ppci_dev,devs);
5165 + //Initialize APU and register the Mixer /dev/mixer
5166 + // If we support multiple card then we need to keep track of the apuinit pointer too
5167 + // Set the vapu_enable bit
5168 + devs->hwbase->vapuinit = vapu_enable;
5169 + if( Nvaudio_apuinit(devs->hwbase) <= 0) {
5170 + NvRelease_Resources(devs);
5171 + ret = -ENOMEM;
5172 + return ret;
5175 + // ISR should be register after the initialization
5176 + if(request_irq(devs->hwbase->aciirq,&Nvaci_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], devs)) {
5177 + printk(KERN_ERR "Nvsound: IRQ in use \n");
5178 + NvRelease_Resources(devs);
5179 + ret = -EBUSY;
5180 + return ret;
5183 + printk(KERN_INFO "Nvsound: DEV MIXER %d DEV AUDIO %d \n", devs->dev_mixer, devs->dev_audio);
5185 + return 0;
5188 +////////////////////////////////////////////////////////////////////////
5189 +// remove function
5190 +////////////////////////////////////////////////////////////////////////
5191 +static void __devexit Nvaudio_remove(struct pci_dev *ppci_dev)
5193 + Nvaudio_card *card = pci_get_drvdata(ppci_dev);
5194 + printk(KERN_INFO "Nvsound: Audio getting removed %p \n",card);
5195 + if(card) {
5196 + Nv_FreeApuExec();
5197 + NvRelease_Resources(card);
5198 + devs = NULL;
5202 +MODULE_PARM(vapu_enable, "i");
5203 +#define NVAUDIO_MODULE_NAME "nforce_audio"
5204 +static struct pci_driver Nvaudio_pci_driver = {
5205 + name: NVAUDIO_MODULE_NAME,
5206 + id_table: Nvaudio_pci_tbl,
5207 + probe: Nvaudio_probe,
5208 + remove: __devexit_p(Nvaudio_remove),
5211 +////////////////////////////////////////////////////////////////////////
5212 +// init module function
5213 +////////////////////////////////////////////////////////////////////////
5214 +static int __init Nvaudio_init_module (void)
5216 + int ret = 0;
5217 + printk(KERN_INFO "Nvsound: Nvidia Audio Init Module, " __TIME__ " " __DATE__ " version %s \n",
5218 + DRIVERVER);
5219 + ret = pci_module_init(&Nvaudio_pci_driver);
5220 + return ret;
5223 +////////////////////////////////////////////////////////////////////////
5224 +// Module clean function
5225 +////////////////////////////////////////////////////////////////////////
5226 +static void __exit Nvaudio_cleanup_module (void)
5228 + pci_unregister_driver(&Nvaudio_pci_driver);
5231 +module_init(Nvaudio_init_module);
5232 +module_exit(Nvaudio_cleanup_module);