Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Linux Kernel Patch v2.1, patch-2.2.0-pre8 (00/17)

10 views
Skip to first unread message

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part00

lines added deleted
linux/CREDITS : 28 10 3
linux/Documentation/Changes : 23 9 8
linux/Documentation/Configure.help : 244 51 53
linux/Documentation/cdrom/cdrom-standard.tex : 97 15 13
linux/Documentation/cdrom/ide-cd : 7 0 1
linux/Documentation/fb/matroxfb.txt : 296 136 93
linux/Documentation/fb/vesafb.txt : 98 38 18
linux/Documentation/logo.txt : 7 1 1
linux/Documentation/sound/OPL3-SA2 : 8 1 1
linux/Documentation/sound/README.OSS : 1484 1484 0
linux/Documentation/sound/README.modules : 99 99 0
linux/MAINTAINERS : 56 12 10
linux/Makefile : 17 2 2
linux/REPORTING-BUGS : 14 2 2
linux/arch/alpha/Makefile : 40 17 2
linux/arch/alpha/config.in : 8 0 2
linux/arch/alpha/kernel/alpha_ksyms.c : 21 8 0
linux/arch/alpha/kernel/irq.c : 15 6 3
linux/arch/alpha/kernel/process.c : 21 1 6
linux/arch/alpha/kernel/setup.c : 106 40 60
linux/arch/alpha/kernel/smp.c : 26 3 3
linux/arch/alpha/lib/Makefile : 8 1 1
linux/arch/alpha/lib/semaphore.S : 184 184 0
linux/arch/arm/config.in : 8 0 2
linux/arch/i386/config.in : 8 0 2
linux/arch/i386/defconfig : 22 7 2
linux/arch/i386/kernel/apm.c : 319 90 52
linux/arch/i386/kernel/entry.S : 8 1 1
linux/arch/i386/kernel/head.S : 18 8 4
linux/arch/i386/kernel/process.c : 61 15 26
linux/arch/i386/lib/checksum.S : 82 14 17
linux/arch/m68k/config.in : 8 0 2
linux/arch/mips/config.in : 8 0 2
linux/arch/ppc/config.in : 7 0 1
linux/arch/sparc/config.in : 8 0 2
linux/arch/sparc64/config.in : 8 0 2
linux/drivers/block/hd.c : 7 1 0
linux/drivers/block/ide-cd.c : 69 10 14
linux/drivers/block/ide-cd.h : 80 9 10
linux/drivers/block/ide-disk.c : 10 2 2
linux/drivers/block/ide-dma.c : 12 5 1
linux/drivers/block/ide-pci.c : 26 6 0
linux/drivers/block/ide.c : 12 6 0
linux/drivers/block/loop.c : 7 1 0
linux/drivers/block/ps2esdi.c : 7 1 0
linux/drivers/cdrom/cdrom.c : 113 30 18
linux/drivers/char/bttv.c : 2021 965 331
linux/drivers/char/bttv.h : 141 39 12
linux/drivers/char/hfmodem/main.c : 8 1 1
linux/drivers/char/i2c.c : 61 8 3
linux/drivers/char/lp_m68k.c : 24 0 4
linux/drivers/char/misc.c : 25 0 4
linux/drivers/char/msp3400.c : 805 270 122
linux/drivers/char/msp3400.h : 30 11 11
linux/drivers/char/n_tty.c : 12 2 2
linux/drivers/char/pc_keyb.c : 90 49 12
linux/drivers/char/pc_keyb.h : 8 2 0
linux/drivers/char/pcxx.c : 7 1 0
linux/drivers/char/rtc.c : 8 1 1
linux/drivers/char/saa5249.c : 8 1 1
linux/drivers/char/serial.c : 8 1 1
linux/drivers/char/tty_io.c : 25 0 4
linux/drivers/char/tuner.c : 114 38 10
linux/drivers/char/videodev.c : 164 57 10
linux/drivers/net/3c523.c : 69 10 10
linux/drivers/net/3c59x.c : 31 4 0
linux/drivers/net/Config.in : 16 2 1
linux/drivers/net/Makefile : 7 2 2
linux/drivers/net/Space.c : 37 3 7
linux/drivers/net/acenic.c : 100 25 13
linux/drivers/net/eepro100.c : 15 2 0
linux/drivers/net/eexpress.c : 7 1 0
linux/drivers/net/hamradio/baycom_ser_fdx.c : 7 1 0
linux/drivers/net/hamradio/baycom_ser_hdx.c : 7 1 0
linux/drivers/net/hamradio/soundmodem/sm.c : 7 1 0
linux/drivers/net/ltpc.c : 8 1 1
linux/drivers/net/pcnet32.c : 316 86 44
linux/drivers/net/ppp.c : 55 20 1
linux/drivers/net/rcif.h : 145 66 2
linux/drivers/net/rclanmtl.c : 2307 2307 0
linux/drivers/net/rclanmtl.h : 637 637 0
linux/drivers/net/rcmtl.c : 2058 0 2058
linux/drivers/net/rcmtl.h : 580 0 580
linux/drivers/net/rcpci45.c : 2012 893 797
linux/drivers/net/znet.c : 13 2 2
linux/drivers/pci/oldproc.c : 67 11 8
linux/drivers/scsi/ChangeLog.ncr53c8xx : 16 13 0
linux/drivers/scsi/NCR53c406a.c : 24 4 4
linux/drivers/scsi/aha152x.c : 17 2 2
linux/drivers/scsi/aic7xxx.c : 32 6 6
linux/drivers/scsi/hosts.c : 9 3 0
linux/drivers/scsi/i91uscsi.c : 12 2 2
linux/drivers/scsi/ide-scsi.c : 18 5 0
linux/drivers/scsi/mac_NCR5380.c : 29 4 4
linux/drivers/scsi/mac_scsi.c : 8 1 1
linux/drivers/scsi/ncr53c8xx.c : 132 21 15
linux/drivers/scsi/ncr53c8xx.h : 39 16 3
linux/drivers/scsi/scsi.c : 8 1 1
linux/drivers/scsi/scsi_obsolete.c : 8 1 1
linux/drivers/scsi/sd.c : 58 9 9
linux/drivers/scsi/sr.c : 52 1 11
linux/drivers/sound/Config.in : 31 11 13
linux/drivers/sound/Makefile : 9 2 1
linux/drivers/sound/README.FIRST : 4 0 1
linux/drivers/sound/README.blurb : 10 0 10
linux/drivers/sound/README.wavefront : 375 0 375
linux/drivers/sound/Readme : 186 0 186
linux/drivers/sound/Readme.cards : 1227 0 1227
linux/drivers/sound/Readme.linux : 85 0 85
linux/drivers/sound/Readme.modules : 99 0 99
linux/drivers/sound/ad1848.c : 18 3 2
linux/drivers/sound/lowlevel/README : 28 11 7
linux/drivers/sound/pas2_card.c : 68 14 4
linux/drivers/sound/pas2_midi.c : 8 1 1
linux/drivers/sound/pas2_pcm.c : 8 1 1
linux/drivers/sound/sb.h : 44 10 5
linux/drivers/sound/sb_audio.c : 335 14 263
linux/drivers/sound/sb_common.c : 506 57 323
linux/drivers/sound/sb_ess.c : 1682 1682 0
linux/drivers/sound/sb_ess.h : 34 34 0
linux/drivers/sound/sb_mixer.c : 473 14 359
linux/drivers/sound/sequencer.c : 20 0 4
linux/drivers/sound/skeleton.c : 224 224 0
linux/drivers/sound/sound_core.c : 23 1 2
linux/drivers/sound/soundcard.c : 28 0 4
linux/drivers/sound/wavfront.c : 7 1 0
linux/drivers/sound/wf_midi.c : 7 1 0
linux/drivers/video/matroxfb.c : 120 23 18
linux/fs/Config.in : 6 2 0
linux/fs/autofs/dirhash.c : 8 1 1
linux/fs/buffer.c : 48 2 18
linux/fs/dcache.c : 31 3 4
linux/fs/exec.c : 27 3 6
linux/fs/isofs/namei.c : 23 4 2
linux/fs/namei.c : 257 79 66
linux/fs/nfs/dir.c : 37 13 7
linux/fs/nfsd/nfsfh.c : 8 1 1
linux/fs/nfsd/vfs.c : 21 7 1
linux/fs/proc/array.c : 356 115 59
linux/fs/proc/root.c : 40 27 0
linux/fs/select.c : 288 86 72
linux/fs/ufs/balloc.c : 17 2 2
linux/fs/ufs/cylinder.c : 35 4 4
linux/fs/ufs/dir.c : 7 1 0
linux/fs/ufs/file.c : 9 0 3
linux/fs/ufs/ialloc.c : 8 1 1
linux/fs/ufs/inode.c : 15 2 2
linux/fs/ufs/namei.c : 18 2 3
linux/fs/ufs/super.c : 153 18 22
linux/fs/ufs/symlink.c : 15 2 2
linux/fs/vfat/namei.c : 1066 285 371
linux/include/asm-alpha/processor.h : 16 2 1
linux/include/asm-alpha/semaphore.h : 249 172 15
linux/include/asm-alpha/system.h : 9 3 0
linux/include/asm-arm/processor.h : 12 1 3
linux/include/asm-arm/semaphore.h : 8 1 1
linux/include/asm-i386/processor.h : 16 2 1
linux/include/asm-i386/semaphore.h : 135 85 5
linux/include/asm-i386/softirq.h : 10 2 1
linux/include/asm-i386/string.h : 17 2 2
linux/include/asm-m68k/processor.h : 16 2 1
linux/include/asm-m68k/semaphore.h : 8 1 1
linux/include/asm-mips/processor.h : 18 3 2
linux/include/asm-mips/semaphore.h : 8 1 1
linux/include/asm-ppc/processor.h : 19 4 2
linux/include/asm-ppc/semaphore.h : 8 1 1
linux/include/asm-sparc/processor.h : 7 1 0
linux/include/asm-sparc/semaphore.h : 8 1 1
linux/include/asm-sparc64/processor.h : 7 1 0
linux/include/asm-sparc64/semaphore.h : 8 1 1
linux/include/linux/cdrom.h : 9 1 2
linux/include/linux/dcache.h : 19 9 1
linux/include/linux/fs.h : 8 0 2
linux/include/linux/hdreg.h : 7 1 0
linux/include/linux/i2c.h : 49 19 4
linux/include/linux/if_pppvar.h : 18 3 2
linux/include/linux/kmod.h : 12 8 0
linux/include/linux/mm.h : 86 15 21
linux/include/linux/pci.h : 16 3 0
linux/include/linux/poll.h : 108 39 12
linux/include/linux/ppp_defs.h : 16 2 1
linux/include/linux/quota.h : 8 1 1
linux/include/linux/sched.h : 64 14 6
linux/include/linux/videodev.h : 51 11 2
linux/include/net/tcp.h : 11 3 2
linux/kernel/exit.c : 7 1 0
linux/kernel/fork.c : 101 35 11
linux/kernel/ksyms.c : 9 2 1
linux/kernel/sched.c : 17 2 2
linux/mm/filemap.c : 87 6 57
linux/mm/memory.c : 95 28 35
linux/mm/mmap.c : 369 202 51
linux/mm/mmap_avl.c : 374 374 0
linux/mm/vmalloc.c : 11 3 1
linux/mm/vmscan.c : 23 5 2
linux/net/ipv4/ip_input.c : 18 3 1
linux/net/ipv4/ip_masq.c : 26 4 2
linux/net/ipv4/ipconfig.c : 34 10 4
linux/net/ipv4/ipmr.c : 16 1 2
linux/net/ipv4/route.c : 24 3 1
linux/net/ipv4/tcp.c : 8 1 1
linux/net/ipv4/tcp_input.c : 156 39 26
linux/net/ipv4/tcp_output.c : 40 9 3
linux/net/ipv6/addrconf.c : 17 2 2
linux/net/ipv6/af_inet6.c : 7 1 0
linux/net/ipv6/ndisc.c : 10 2 1
linux/net/ipx/af_ipx.c : 25 8 4
linux/net/socket.c : 8 1 1
linux/net/sunrpc/sched.c : 58 20 7
linux/net/sunrpc/xprt.c : 105 15 12
linux/net/unix/af_unix.c : 17 2 2
linux/scripts/header.tk : 119 40 40
linux/scripts/tail.tk : 88 25 28
linux/scripts/tkgen.c : 28 13 0
linux/scripts/tkparse.c : 51 26 3
linux/scripts/tkparse.h : 14 4 4
linux/scripts/ver_linux : 18 5 2
--
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part01

#!/bin/sh
# This is a shell archive
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
# existing files will NOT be overwritten unless -c is specified
#
# This is part 01 of a 17 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= patch-2.2.0-pre8 ==============
if test -f 'patch-2.2.0-pre8' -a X"$1" != X"-c"; then
echo 'x - skipping patch-2.2.0-pre8 (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.2.0-pre8 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.2.0-pre8' &&
diff -u --recursive --new-file v2.2.0-pre7/linux/CREDITS linux/CREDITS
--- v2.2.0-pre7/linux/CREDITS Wed Jan 13 15:00:40 1999
+++ linux/CREDITS Fri Jan 15 14:36:20 1999
@@ -16,6 +16,13 @@
X S: (ask for current address)
X S: Finland
X
+N: Dave Airlie
+E: air...@linux.ie
+W: http://www.csn.ul.ie/~airlied
+D: NFS over TCP patches
+S: University of Limerick
+S: Ireland
+
X N: Werner Almesberger
X E: werner.al...@lrc.di.epfl.ch
X D: dosfs, LILO, some fd features, various other hacks here and there
@@ -1720,11 +1727,11 @@
X S: USA
X
X N: Mike Shaver
-E: sha...@netscape.com
-W: http://people.netscape.com/shaver/
+E: sha...@hungry.org
+W: http://www.hungry.org/~shaver/
X D: MIPS work, /proc/sys/net, misc net hacking
X S: 149 Union St.
-S: Ottawa, Ontario
+S: Kingston, Ontario
X S: Canada K7L 2P4
X
X N: John Shifflett
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/Changes linux/Documentation/Changes
--- v2.2.0-pre7/linux/Documentation/Changes Tue Dec 22 14:16:53 1998
+++ linux/Documentation/Changes Thu Jan 14 10:51:51 1999
@@ -85,14 +85,15 @@
X compiled under 2.0 or earlier kernels should be replaced with ones
X compiled under 2.1, for example.
X
- As of 2.1.115, Unix98 pty support was added as an option, and
-support for the deprecated major 4 /dev/ttyp* devices was removed. If
-necessary (eg, you get "out of pty" error messages when you obviously
-are not out of pty's), create major 3 /dev/tty* and major 2 /dev/pty*
-devices (see Documentation/devices.txt for more information). If you
-want to use the Unix98 ptys, you should be running at least
-glibc-2.0.9x, and you must switch completely to Unix98 pty's. The
-general procedure for configuring Unix98 pty support is:
+ As of 2.1.115, support for the deprecated major 4 /dev/ttyp* devices
+was removed. If necessary (eg, you get "out of pty" error messages when
+you obviously are not out of pty's), create major 3 /dev/tty* and major 2
+/dev/pty* devices (see Documentation/devices.txt for more information).
+
+ Optional support for Unix98 pty devices has also been added. If you
+want to use the Unix98 ptys, you should be running at least glibc-2.0.9x,
+and you must switch completely to Unix98 pty's. The general procedure
+for configuring Unix98 pty support is:
X
X - Compile your kernel with CONFIG_UNIX98_PTYS and CONFIG_DEVPTS_FS.
X - mknod /dev/ptmx c 5 2
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.0-pre7/linux/Documentation/Configure.help Wed Jan 13 15:00:41 1999
+++ linux/Documentation/Configure.help Sat Jan 16 16:57:53 1999
@@ -1343,8 +1343,8 @@
X boot time ("man dmesg"), please follow the instructions at the top
X of include/linux/pci.h.
X
-PCI BIOS support
-CONFIG_PCI_BIOS
+PCI access mode
+CONFIG_PCI_GOBIOS
X If you have enabled PCI bus support above, you probably want to
X allow Linux to use your PCI BIOS to detect the PCI devices and
X determine their configuration. Note: some old PCI motherboards have
@@ -1355,8 +1355,6 @@
X Except for some special cases (embedded systems with no BIOS), you
X probably should say Y here.
X
-PCI direct access support
-CONFIG_PCI_DIRECT
X If you don't want to use the PCI BIOS (e.g., because you run some
X embedded system with no BIOS at all) or Linux says it cannot use
X your PCI BIOS, you can enable direct PCI hardware here. It might
@@ -1730,6 +1728,18 @@
X Say N unless you have such a graphics board or plan to get one
X before you next recompile the kernel.
X
+Apollo support
+CONFIG_APOLLO
+ Say Y here if you want to run Linux on an MC680x0-based Apollo
+ Domain workstation such as the DN3500.
+
+Apollo 3c505 support
+CONFIG_APOLLO_ELPLUS
+ Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
+ If you don't have one made for Apollos, you can use one from a PC,
+ except that your Apollo won't be able to boot from it (because the
+ code in the ROM will be for a PC).
+
X Atari native chipset support
X CONFIG_FB_ATARI
X This is the frame buffer device driver for the builtin graphics
@@ -1799,7 +1809,7 @@
X
X Matrox unified accelerated driver
X CONFIG_FB_MATROX
- Say Y here if you have Matrox Millennium, Matrox Milleinnium II,
+ Say Y here if you have Matrox Millennium, Matrox Millennium II,
X Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
X Mystique G200, Matrox Millennium G200 or Matrox Marvel G200 in your
X box. At this time, G100, Mystique G200 and Marvel G200 support is
@@ -1807,7 +1817,7 @@
X matroxfb.o will be created. You can pass parameters into driver if
X it is compiled into kernel by specifying "video=matrox:XXX", where
X meaning of XXX you can found at the end of main source file
- (drivers/video/matroxfb.c) at boottime. Same parameters can be
+ (drivers/video/matroxfb.c) at boot time. Same parameters can be
X passed into insmod if driver is used as module.
X
X Matrox Millennium support
@@ -1826,9 +1836,10 @@
X and 32 bpp packed pixel. You can also use font widths different
X from 8.
X
-Matrox G100 support
+Matrox G100/G200 support
X CONFIG_FB_MATROX_G100
- Say Y here if you have Matrox Productiva G100 in the box. If you
+ Say Y here if you have Matrox Productiva G100, Matrox Mystique G200,
+ Matrox Marvel G200 or Matrox Millennium G200 in the box. If you
X select "Advanced lowlevel driver options", you should check 8 bpp
X packed pixel, 16 bpp packed pixel, 24 bpp packed pixel and 32 bpp
X packed pixel. You can also use font widths different from 8.
@@ -3588,11 +3599,12 @@
X
X Adaptec AHA152X/2825 support
X CONFIG_SCSI_AHA152X
- This is support for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825
- SCSI host adapters. It is explained in section 3.3 of the
- SCSI-HOWTO, available via FTP (user: anonymous) at
- ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. You might also want to
- read the comments at the top of drivers/scsi/aha152x.c.
+ This is support for the AVA-1505 (irq etc must be manually specified),
+ AHA-1510, AHA-1520, AHA-1522, and AHA-2825 SCSI host adapters. It is
+ explained in section 3.3 of the SCSI-HOWTO, available via FTP
+ (user: anonymous) at ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. You
+ might also want to read the comments at the top of
+ drivers/scsi/aha152x.c.
X
X This driver is also available as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want).
@@ -3799,7 +3811,7 @@
X enable elevator sorting
X CONFIG_SCSI_U14_34F_LINKED_COMMANDS
X This option enables elevator sorting for all probed SCSI disks and
- CDROMs. It definetly reduces the average seek distance when doing
+ CDROMs. It definitely reduces the average seek distance when doing
X random seeks, but this does not necessarily results in a noticeable
X performance improvement: your mileage may vary...
X The safe answer is N.
@@ -4008,7 +4020,7 @@
X that can be queued to any device, when tagged command queuing is
X possible. The default value is 32. Minimum is 2, maximum is 64.
X Modern hard disks are able to support 64 tags and even more, but
- donnot seem to be faster when more than 32 tags are being used.
+ do not seem to be faster when more than 32 tags are being used.
X
X So, the normal answer here is to go with the default value 32 unless
X you are using very large hard disks with large cache (>= 1 MB) that
@@ -4144,6 +4156,17 @@
X say M here and read Documentation/modules.txt. The module will be
X called initio.o
X
+Initio 91XXU(W) SCSI support
+CONFIG_SCSI_INITIO
+ This is support for the Initio 91XXU(W) SCSI host adapter.
+ Please read the SCSI-HOWTO, available via FTP (user: anonymous) at
+ ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read Documentation/modules.txt. The module will be
+ called initio.o
+
X PAS16 SCSI support
X CONFIG_SCSI_PAS16
X This is support for a SCSI host adapter. It is explained in section
@@ -4308,7 +4331,7 @@
X CONFIG_SCSI_EATA_LINKED_COMMANDS
X This option enables elevator sorting for all probed SCSI disks and
X CDROMs. It definetly reduces the average seek distance when doing
- random seeks, but this does not necessarily results in a noticeable
+ random seeks, but this does not necessarily result in a noticeable
X performance improvement: your mileage may vary...
X The safe answer is N.
X
@@ -5195,27 +5218,6 @@
X The module will be called cosa.o. For general information about
X modules read Documentation/modules.txt.
X
-COSA/SRP sync serial boards support
-CONFIG_COSA
- This is a driver for COSA and SRP synchronous serial boards.
- These boards enable to connect synchronous serial devices (for
- example base-band modems, or any other device with the X.21, V.24,
- V.35 or V.36 interface) to your Linux box. The cards can work
- as the character device, synchronous PPP network device, or the Cisco
- HDLC network device.
-
- To actually use the COSA or SRP board, you will need user-space
- utilities for downloading the firmware to the cards and to set
- them up. Look at the http://www.fi.muni.cz/~kas/cosa/ for more
- information about the cards (including the pointer to the user-space
- utilities). You can also read the comment at the top of the
- drivers/net/cosa.c for details about the cards and the driver itself.
-
- The driver will be compiled as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called cosa.o. For general information about
- modules read Documentation/modules.txt.
-
X WAN Drivers
X CONFIG_WAN_DRIVERS
X Say Y to this option if your Linux box contains a WAN card and you
@@ -6275,16 +6277,6 @@
X under Linux, say Y here (you must also remember to enable the driver
X for your HIPPI card below). Most people will say N here.
X
-CERN HIPPI PCI adapter support
-CONFIG_CERN_HIPPI
- Say Y here if this is your PCI HIPPI network card.
-
- This driver is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called cern_hippi.o. If you want to compile it as
- a module, say M here and read Documentation/modules.txt. If unsure,
- say N.
-
X Essential RoadRunner HIPPI PCI adapter support
X CONFIG_ROADRUNNER
X Say Y here if this is your PCI HIPPI network card.
@@ -7024,7 +7016,7 @@
X
X To use the automounter you need the user-space tools from
X ftp://ftp.kernel.org/pub/linux/daemons/autofs; you also want to
- answer Y to "NFS filesystem support", above.
+ answer Y to "NFS filesystem support", below.
X
X If you want to compile this as a module ( = code which can be
X inserted in and removed from the running kernel whenever you want),
@@ -7040,7 +7032,7 @@
X OpenBSD and NeXTstep) use a filesystem called UFS. Some System V
X Unixes can create and mount hard disk partitions and diskettes using
X this filesystem as well. Saying Y here will allow you to read from
- and write to these partitions and diskettes.
+ these partitions and diskettes.
X
X If you only intend to mount files from some other Unix over the
X network using NFS, you don't need the UFS filesystem support (but
@@ -7062,6 +7054,12 @@
X
X If you haven't heard about all of this before, it's safe to say N.
X
+UFS filesystem write support
+CONFIG_UFS_FS_WRITE
+ You will be able to write to 4.4BSD (e.g. FreeBSD, NetBSD and
+ OpenBSD) and SunOS partitions and diskettes if you say Y to this
+ option in addition to "UFS filesystem support", above.
+
X BSD disklabel (FreeBSD partition tables) support
X CONFIG_BSD_DISKLABEL
X FreeBSD uses its own hard disk partition scheme on your PC. It
@@ -8499,7 +8497,7 @@
X CONFIG_APM_IGNORE_SUSPEND_BOUNCE
X This option is necessary on the Dell Inspiron 3200 and others, but
X should be safe for all other laptops. When enabled, a system suspend
- event that occurs within one second of a resume is ignored. Without
+ event that occurs within three seconds of a resume is ignored. Without
X this the Inspiron will shut itself off a few seconds after you open
X the lid, requiring you to press the power button to resume it a
X second time.
@@ -9265,7 +9263,7 @@
X CONFIG_AEDSP16_MPU401
X Answer Y if you want your audio card to emulate the MPU-401 midi
X interface. You should then say Y to "MPU-401 support".
- You have to hote that the I/O base for MPU-401 support of aedsp16 is
+ You have to note that the I/O base for MPU-401 support of aedsp16 is
X the same you have selected for "MPU-401 support". If you are using
X this driver as a module you have to specify the MPU I/O base address
X with the parameter 'mpu_base=0xNNN'.
@@ -10542,7 +10540,7 @@
X
X Initial kernel command line
X CONFIG_CMDLINE
- On some architectures (EBSA285, EBSA110 and Corel Netwinder), there is
+ On some architectures (EBSA285, EBSA110 and Corel NetWinder), there is
X currently no way for the boot loader to pass arguments to the kernel.
X For these architectures, you should supply some command-line options
X at build time by entering them here. As a minimum, you should specify
@@ -10599,7 +10597,7 @@
X IrLAP Compression support
X CONFIG_IRDA_COMPRESSION
X Compression is _not_ part of the IrDA(tm) protocol specification,
- but its working great! Linux is the first to try out compresson
+ but it's working great! Linux is the first to try out compression
X support at the IrLAP layer. This means that you will only benefit
X from compression if you are running a Linux <-> Linux configuration
X
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/cdrom/cdrom-standard.tex linux/Documentation/cdrom/cdrom-standard.tex
--- v2.2.0-pre7/linux/Documentation/cdrom/cdrom-standard.tex Sat May 2 14:19:50 1998
+++ linux/Documentation/cdrom/cdrom-standard.tex Mon Jan 18 12:47:33 1999
@@ -23,8 +23,9 @@
X \begin{document}
X \title{A \linux\ \cdrom\ standard}
X \author{David van Leeuwen\\{\normalsize\tt da...@ElseWare.cistron.nl}
-\\{\footnotesize updated by Erik Andersen {\tt(ande...@debian.org)}}}
-\date{19 November 1997}
+\\{\footnotesize updated by Erik Andersen {\tt(ande...@debian.org)}}
+\\{\footnotesize updated by Jens Axboe {\tt(ax...@image.dk)}}}
+\date{11 January 1999}
X
X \maketitle
X
@@ -145,7 +146,7 @@
X low-level \cdrom\ device drivers. The \UCD\ now provides another
X software-level, that separates the $ioctl()$ and $open()$ implementation
X from the actual hardware implementation. Note that this effort has
-made few changes which will effect a user's application programs. The
+made few changes which will affect a user's application programs. The
X greatest change involved moving the contents of the various low-level
X \cdrom\ drivers' header files to the kernel's cdrom directory. This was
X done to help ensure that the user is only presented with only one cdrom
@@ -232,7 +233,7 @@
X struct& cdrom_device_ops\ \{ \hidewidth\cr
X &int& (* open)(struct\ cdrom_device_info *, int)\cr
X &void& (* release)(struct\ cdrom_device_info *);\cr
- &int& (* drive_status)(struct\ cdrom_device_info *);\cr
+ &int& (* drive_status)(struct\ cdrom_device_info *, int);\cr
X &int& (* media_changed)(struct\ cdrom_device_info *, int);\cr
X &int& (* tray_move)(struct\ cdrom_device_info *, int);\cr
X &int& (* lock_door)(struct\ cdrom_device_info *, int);\cr
@@ -286,12 +287,13 @@
X \noalign{\medskip}
X & kdev_t& dev;& device number (incorporates minor)\cr
X & int& mask;& mask of capability: disables them \cr
- &const\ int& speed;& maximum speed for reading data \cr
- &const\ int& capacity;& number of discs in a jukebox \cr
+ & int& speed;& maximum speed for reading data \cr
+ & int& capacity;& number of discs in a jukebox \cr
X \noalign{\medskip}
X &int& options : 30;& options flags \cr
- &long& mc_flags : 2;& media-change buffer flags \cr
+ &unsigned& mc_flags : 2;& media-change buffer flags \cr
X & int& use_count;& number of times device is opened\cr
+ & char& name[20];& name of the device type\cr
X \}\cr
X }$$
X Using this $struct$, a linked list of the registered minor devices is
@@ -371,13 +373,13 @@
X allocated buffers in the VFS is taken care of by the routine in
X \cdromc. This is the only function returning type $void$.
X
-\subsection{$Int\ drive_status(struct\ cdrom_device_info * cdi)$}
+\subsection{$Int\ drive_status(struct\ cdrom_device_info * cdi, int\ slot_nr)$}
X \label{drive status}
X
X The function $drive_status$, if implemented, should provide
X information on the status of the drive (not the status of the disc,
-which may or may not be in the drive). In \cdromh\ the possibilities
-are listed:
+which may or may not be in the drive). If the drive is not a changer,
+$slot_nr$ should be ignored. In \cdromh\ the possibilities are listed:
X $$
X \halign{$#$\ \hfil&$/*$ \rm# $*/$\hfil\cr
X CDS_NO_INFO& no information available\cr
@@ -810,7 +812,7 @@
X
X
X \subsection{$Int\ cdrom_ioctl(struct\ inode *ip, struct\ file *fp,
- unsigned\ int\ cmd, unsigned\ long\ arg)$}
+unsigned\ int\ cmd, unsigned\ long\ arg)$}
X \label{cdrom-ioctl}
X
X This function handles all the standard $ioctl$ requests for \cdrom\
@@ -833,7 +835,7 @@
X \item[CDROMEJECT_SW] If $arg\not=0$, set behavior to auto-close (close
X tray on first open) and auto-eject (eject on last release), otherwise
X set behavior to non-moving on $open()$ and $release()$ calls.
-\item[CDROM_GET_MCN or CDROM_GET_UPC] Get the Media Catalog Number from a CD.
+\item[CDROM_GET_MCN] Get the Media Catalog Number from a CD.
X \end{description}
X
X \subsubsection{$Ioctl$s routed through $audio_ioctl()$}
@@ -931,7 +933,6 @@
X CDS_NO_DISC& no disc is inserted, or tray is opened\cr
X CDS_AUDIO& Audio disc (2352 audio bytes/frame)\cr
X CDS_DATA_1& data disc, mode 1 (2048 user bytes/frame)\cr
- CDS_DATA_2& data disc, mode 2 (2336 user bytes/frame)\cr
X CDS_XA_2_1& mixed data (XA), mode 2, form 1 (2048 user bytes)\cr
X CDS_XA_2_2& mixed data (XA), mode 2, form 1 (2324 user bytes)\cr
X CDS_MIXED& mixed audio/data disc\cr
@@ -942,6 +943,7 @@
X
X \item[CDROM_CHANGER_NSLOTS] Returns the number of slots in a
X juke-box.
+\item[CDROMRESET] Reset the drive.
X \end{description}
X
X \subsubsection{Device dependent $ioctl$s}
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/cdrom/ide-cd linux/Documentation/cdrom/ide-cd
--- v2.2.0-pre7/linux/Documentation/cdrom/ide-cd Sun Nov 8 14:02:41 1998
+++ linux/Documentation/cdrom/ide-cd Mon Jan 18 12:47:33 1999
@@ -2,7 +2,6 @@
X Originally by scott snyder <sny...@fnald0.fnal.gov> (19 May 1996)
X Carrying on the torch is: Erik Andersen <ande...@debian.org>
X New maintainers (19 Oct 1998): Jens Axboe <ax...@image.dk>
- Chris Zwilling <ch...@cloudnet.com>
X
X 1. Introduction
X ---------------
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt
--- v2.2.0-pre7/linux/Documentation/fb/matroxfb.txt Fri Jan 8 22:35:58 1999
+++ linux/Documentation/fb/matroxfb.txt Fri Jan 15 13:56:49 1999
@@ -22,36 +22,61 @@
X How to use it?
X ==============
X
-Switching modes is done using the video=matrox:vesa=... boot parameter
+Switching modes is done using the video=matrox:vesa:... boot parameter
X or using `fbset' program.
X
+If you want, for example, enable a resolution of 1280x1024x24bpp you should
+pass to the kernel this command line: "video=matrox:vesa:0x1BB".
+Note that the same line, if 'appended' as a lilo parameter in lilo.conf will
+read "video=matrox:vesa:443" because lilo pass integer parameters as decimal
+numbers to the kernel.
+
X You should compile in both vgacon (to boot if you remove you Matrox from
X box) and matroxfb (for graphics mode). You should not compile-in vesafb
X unless you have primary display on non-Matrox VBE2.0 device (see
X Documentation/vesafb.txt for details).
X
-Currently supported video modes are (through vesa=... interface, PowerMac
-has (as addon) compatibility code.
+Currently supported video modes are (through vesa:... interface, PowerMac
+has [as addon] compatibility code):
+
+
+[Graphic modes]
+
+bpp | 640x400 640x480 768x576 800x600 960x720
+----+--------------------------------------------
+ 4 | 0x12 0x102
+ 8 | 0x100 0x101 0x180 0x103 0x188
+ 15 | 0x110 0x181 0x113 0x189
+ 16 | 0x111 0x182 0x114 0x18A
+ 24 | 0x1B2 0x184 0x1B5 0x18C
+ 32 | 0x112 0x183 0x115 0x18B
+
+
+[Graphic modes (continued)]
X
-bpp | 640x400 640x480 768x576 800x600 960x720 1024x768 1152x864 1280x1024 1408x1056 1600x1200
-----+----------------------------------------------------------------------------------------------
- 4 | 0x12 0x102 0x104 0x106
- 8 | 0x100 0x101 0x180 0x103 0x188 0x105 0x190 0x107 0x198 0x11C
- 15 | 0x110 0x181 0x113 0x189 0x116 0x191 0x119 0x199 0x11D
- 16 | 0x111 0x182 0x114 0x18A 0x117 0x192 0x11A 0x19A 0x11E
- 24 | 0x1B2 0x184 0x1B5 0x18C 0x1B8 0x194 0x1BB 0x19C 0x1BF
- 32 | 0x112 0x183 0x115 0x18B 0x118 0x193 0x11B 0x19B
+bpp | 1024x768 1152x864 1280x1024 1408x1056 1600x1200
+----+------------------------------------------------
+ 4 | 0x104 0x106
+ 8 | 0x105 0x190 0x107 0x198 0x11C
+ 15 | 0x116 0x191 0x119 0x199 0x11D
+ 16 | 0x117 0x192 0x11A 0x19A 0x11E
+ 24 | 0x1B8 0x194 0x1BB 0x19C 0x1BF
+ 32 | 0x118 0x193 0x11B 0x19B
+
+
+[Text modes]
X
X text | 640x400 640x480 1056x344 1056x400 1056x480
X -----+------------------------------------------------
X 8x8 | 0x1C0 0x108 0x10A 0x10B 0x10C
X 8x16 | 2, 3, 7 0x109
X
-You can enter these number either hexadecimal (leading `0x') or decimal (0x100 = 256). You can also
-use value + 512 to achieve compatibility with your old number passed to vesafb.
+You can enter these number either hexadecimal (leading `0x') or decimal
+(0x100 = 256). You can also use value + 512 to achieve compatibility
+with your old number passed to vesafb.
X
-Non-listed number can be achieved by more complicated command-line, for example
-1600x1200x32bpp can be specified by `video=matrox:vesa:0x11C,depth:32'.
+Non-listed number can be achieved by more complicated command-line, for
+example 1600x1200x32bpp can be specified by `video=matrox:vesa:0x11C,depth:32'.
X
X
X X11
@@ -70,8 +95,8 @@
X =======
X
X Driver contains SVGALib compatibility code. It is turned on by choosing textual
-mode for console. You can do it at boottime by using videomode 2,3,7,0x108-0x10C
-or 0x1C0. At runtime, `fbset -depth 0' does this work.
+mode for console. You can do it at boottime by using videomode
+2,3,7,0x108-0x10C or 0x1C0. At runtime, `fbset -depth 0' does this work.
X Unfortunately, after SVGALib application exits, screen contents is corrupted.
X Switching to another console and back fixes it. I hope that it is SVGALib and
X not mine problem, but I'm not sure.
@@ -91,9 +116,9 @@
X memory usable for on-screen display (i.e. max. 8MB).
X disabled - do not load driver; you can use also `off', but `disabled'
X is here too.
-enabled - load driver, if you have `video=matrox:disabled' in LILO configuration,
- you can override it by this (you cannot override `off').
- It is default.
+enabled - load driver, if you have `video=matrox:disabled' in LILO
+ configuration, you can override it by this (you cannot override
+ `off'). It is default.
X noaccel - do not use acceleration engine. It does not work on Alphas.
X accel - use acceleration engine. It is default.
X nopan - create initial consoles with vyres = yres, thus disabling virtual
@@ -102,95 +127,115 @@
X It is default.
X nopciretry - disable PCI retries. It is needed for some broken chipsets,
X it is autodetected for intel's 82437. In this case device does
- not comply to PCI 2.1 specs (it will not guarantee that every transaction
- terminate with success or retry in 32 PCLK).
+ not comply to PCI 2.1 specs (it will not guarantee that every
+ transaction terminate with success or retry in 32 PCLK).
X pciretry - enable PCI retries. It is default, except for intel's 82437.
X novga - disables VGA I/O ports. It is default if BIOS did not enable device.
- You should not use this option, some boards then do not restart without
- power off.
-vga - preserve state of VGA I/O ports. It is default. Driver does not enable
- VGA I/O if BIOS did not it (it is not safe to enable it in most cases).
+ You should not use this option, some boards then do not restart
+ without power off.
+vga - preserve state of VGA I/O ports. It is default. Driver does not
+ enable VGA I/O if BIOS did not it (it is not safe to enable it in
+ most cases).
X nobios - disables BIOS ROM. It is default if BIOS did not enable BIOS itself.
- You should not use this option, some boards then do not restart without
- power off.
-bios - preserve state of BIOS ROM. It is default. Driver does not enable BIOS
- if BIOS was not enabled before.
-noinit - tells driver, that devices were already initialized. You should use it
- if you have G100 and/or if driver cannot detect memory, you see strange
- pattern on screen and so on. Devices not enabled by BIOS are still
- initialized. It is default.
+ You should not use this option, some boards then do not restart
+ without power off.
+bios - preserve state of BIOS ROM. It is default. Driver does not enable
+ BIOS if BIOS was not enabled before.
+noinit - tells driver, that devices were already initialized. You should use
+ it if you have G100 and/or if driver cannot detect memory, you see
+ strange pattern on screen and so on. Devices not enabled by BIOS
+ are still initialized. It is default.
X init - driver initializes every device it knows about.
X nomtrr - disables write combining on frame buffer. This slows down driver but
- there is reported minor incompatibility between GUS DMA and XFree under
- high loads if write combining is enabled (sound dropouts).
+ there is reported minor incompatibility between GUS DMA and XFree
+ under high loads if write combining is enabled (sound dropouts).
X mtrr - enables write combining on frame buffer. It speeds up video accesses
- much. It is default. You must have MTRR support enabled in kernel and
- your CPU must have MTRR (f.e. Pentium II have them).
-sgram - tells to driver that you have G200 with SGRAM memory. It has no effect
- without `init'.
-sdram - tells to driver that you have G200 with SDRAM memory. It is a default.
-inv24 - change timings parameters for 24bpp modes on Millenium and Millenium II.
- Specify this if you see strange color shadows around characters.
+ much. It is default. You must have MTRR support enabled in kernel
+ and your CPU must have MTRR (f.e. Pentium II have them).
+sgram - tells to driver that you have G200 with SGRAM memory. It has no
+ effect without `init'.
+sdram - tells to driver that you have G200 with SDRAM memory.
+ It is a default.
+inv24 - change timings parameters for 24bpp modes on Millenium and
+ Millenium II. Specify this if you see strange color shadows around
+ characters.
X noinv24 - use standard timmings. It is default.
X inverse - invert colors on screen (for LCD displays)
X noinverse - show true colors on screen. It is default.
-dev:X - bind driver to device X. Driver numbers device from 0 up to N, where device
- 0 is first `known' device found, 1 second and so on. lspci lists
- devices in this order.
- Default is `every' known device for driver with multihead support and
- first working device (usually dev:0) for driver without multihead support.
+dev:X - bind driver to device X. Driver numbers device from 0 up to N,
+ where device 0 is first `known' device found, 1 second and so on.
+ lspci lists devices in this order.
+ Default is `every' known device for driver with multihead support
+ and first working device (usually dev:0) for driver without
+ multihead support.
X nohwcursor - disables hardware cursor (use software cursor instead).
-hwcursor - enables hardware cursor. It is default. If you are using non-accelerated mode
- (`noaccel' or `fbset -accel false'), software cursor is used (except for
- text mode).
-noblink - disables cursor blinking. Cursor in text mode always blinks (hw limitation).
+hwcursor - enables hardware cursor. It is default. If you are using
+ non-accelerated mode (`noaccel' or `fbset -accel false'), software
+ cursor is used (except for text mode).
+noblink - disables cursor blinking. Cursor in text mode always blinks (hw
+ limitation).
X blink - enables cursor blinking. It is default.
X nofastfont - disables fastfont feature. It is default.
-fastfont:X - enables fastfont feature. X specifies size of memory reserved for font data,
- it must be >= (fontwidth*fontheight*chars_in_font)/8. It is faster on
- Gx00 series, but slower on older cards.
-grayscale - enable grayscale summing. It works in PSEUDOCOLOR modes (text, 4bpp, 8bpp). In
- DIRECTCOLOR modes it is limited to characters displayed through putc/putcs. Direct
- accesses to framebuffer can paint colors.
+fastfont:X - enables fastfont feature. X specifies size of memory reserved for
+ font data, it must be >= (fontwidth*fontheight*chars_in_font)/8.
+ It is faster on Gx00 series, but slower on older cards.
+grayscale - enable grayscale summing. It works in PSEUDOCOLOR modes (text,
+ 4bpp, 8bpp). In DIRECTCOLOR modes it is limited to characters
+ displayed through putc/putcs. Direct accesses to framebuffer
+ can paint colors.
X nograyscale - disable grayscale summing. It is default.
-cross4MB - enables that pixel line can cross 4MB boundary. It is default for non-Millenium.
-nocross4MB - pixel line must not cross 4MB boundary. It is default for Millenium I or II,
- because of these devices have hardware limitations which do not allow this.
- But this option is incompatible with some (if not all yet released) versions
- of XF86_FBDev.
-vesa:X - selects startup videomode. X is number from 0 to 0x1FF, see table above
- for detailed explanation. Default is 640x480, 8bpp if driver has 8bpp support.
- Otherwise first available of 640x350x4bpp, 640x480x15bpp, 640x480x24bpp,
- 640x480x32bpp or 80x25 text (80x25 text is always available).
+cross4MB - enables that pixel line can cross 4MB boundary. It is default for
+ non-Millenium.
+nocross4MB - pixel line must not cross 4MB boundary. It is default for
+ Millenium I or II, because of these devices have hardware
+ limitations which do not allow this. But this option is
+ incompatible with some (if not all yet released) versions of
+ XF86_FBDev.
+vesa:X - selects startup videomode. X is number from 0 to 0x1FF, see table
+ above for detailed explanation. Default is 640x480x8bpp if driver
+ has 8bpp support. Otherwise first available of 640x350x4bpp,
+ 640x480x15bpp, 640x480x24bpp, 640x480x32bpp or 80x25 text
+ (80x25 text is always available).
+
X If you are not satisfied with videomode selected by `vesa' option, you
X can modify it with these options:
-xres:X - horizontal resolution, in pixels. Default is derived from `vesa' option.
-yres:X - vertical resolution, in pixel lines. Default is derived from `vesa' option.
-upper:X - top boundary: lines between end of VSYNC pulse and start of first pixel line
- of picture. Default is derived from `vesa' option.
-lower:X - bottom boundary: lines between end of picture and start of VSYNC pulse.
- Default is derived from `vesa' option.
-vslen:X - length of VSYNC pulse, in lines. Default is derived from `vesa' option.
-left:X - left boundary: pixels between end of HSYNC pulse and first pixel. Default
- is derived from `vesa' option.
-right:X - right boundary: pixels between end of picture and start of HSYNC pulse.
+
+xres:X - horizontal resolution, in pixels. Default is derived from `vesa'
+ option.
+yres:X - vertical resolution, in pixel lines. Default is derived from `vesa'
+ option.
+upper:X - top boundary: lines between end of VSYNC pulse and start of first
+ pixel line of picture. Default is derived from `vesa' option.
+lower:X - bottom boundary: lines between end of picture and start of VSYNC
+ pulse. Default is derived from `vesa' option.
+vslen:X - length of VSYNC pulse, in lines. Default is derived from `vesa'
+ option.
+left:X - left boundary: pixels between end of HSYNC pulse and first pixel.
X Default is derived from `vesa' option.
-hslen:X - length of HSYNC pulse, in pixels. Default is derived from `vesa' option.
-pixclock:X - dotclocks, in ps (picoseconds). Default is derived from `vesa' option and
- from `fh' and `fv' options.
+right:X - right boundary: pixels between end of picture and start of HSYNC
+ pulse. Default is derived from `vesa' option.
+hslen:X - length of HSYNC pulse, in pixels. Default is derived from `vesa'
+ option.
+pixclock:X - dotclocks, in ps (picoseconds). Default is derived from `vesa'
+ option and from `fh' and `fv' options.
X sync:X - sync. pulse - bit 0 inverts HSYNC polarity, bit 1 VSYNC polarity.
- If bit 3 (value 0x08) is set, composite sync instead of HSYNC is generated.
- If bit 5 (value 0x20) is set, sync on green is turned on.
+ If bit 3 (value 0x08) is set, composite sync instead of HSYNC is
+ generated. If bit 5 (value 0x20) is set, sync on green is turned on.
X Default depends on `vesa'.
-depth:X - Bits per pixel: 0=text, 4,8,15,16,24 or 32. Default depends on `vesa'.
-If you know capabilities of your monitor, you can specify some (or all) of `pixclk', `fh'
-and `fv'. In this case, `pixclock' is computed so that pixclock <= maxclk, real_fh <= fh
-and real_fv <= fv.
-maxclk:X - maximum dotclock. X can be specified in MHz, kHz or Hz. Default is `don't care'.
-fh:X - maximum horizontal synchronization frequency. X can be specified in kHz or Hz.
- Default is `don't care'.
-fv:X - maximum vertical frequency. X must be specified in Hz. Default is 70 for modes
- derived from `vesa' with yres <= 400, 60Hz for yres > 400.
+depth:X - Bits per pixel: 0=text, 4,8,15,16,24 or 32. Default depends on
+ `vesa'.
+
+If you know capabilities of your monitor, you can specify some (or all) of
+`pixclk', `fh' and `fv'. In this case, `pixclock' is computed so that
+pixclock <= maxclk, real_fh <= fh and real_fv <= fv.
+
+maxclk:X - maximum dotclock. X can be specified in MHz, kHz or Hz. Default is
+ `don't care'.
+fh:X - maximum horizontal synchronization frequency. X can be specified
+ in kHz or Hz. Default is `don't care'.
+fv:X - maximum vertical frequency. X must be specified in Hz. Default is
+ 70 for modes derived from `vesa' with yres <= 400, 60Hz for
+ yres > 400.
X
X
X Limitations
@@ -198,8 +243,6 @@
X
X There are known and unknown bugs, features and misfeatures.
X Currently there are following known bugs:
- + G100 support does not work as expected, I'm still investigating this one.
- Using `noinit' option works, but only for `first' head :-(
X + SVGALib does not restore screen on exit
X + generic fbcon-cfbX procedures do not work on Alphas. Due to this,
X `noaccel' (and cfb4 accel) driver does not work on Alpha. So everyone
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/fb/vesafb.txt linux/Documentation/fb/vesafb.txt
--- v2.2.0-pre7/linux/Documentation/fb/vesafb.txt Fri Oct 9 13:27:04 1998
+++ linux/Documentation/fb/vesafb.txt Thu Jan 14 22:53:02 1999
@@ -1,16 +1,16 @@
X
-what is vesafb?
+What is vesafb?
X ===============
X
X This is a generic driver for a graphic framebuffer on intel boxes.
X
-Idea is simple: Turn on graphics mode at boot time with the help of
-the BIOS, and use this as framebuffer device /dev/fb0, like the m68k
+The idea is simple: Turn on graphics mode at boot time with the help
+of the BIOS, and use this as framebuffer device /dev/fb0, like the m68k
X (and other) ports do.
X
X This means we decide at boot time whenever we want to run in text or
X graphics mode. Switching mode later on (in protected mode) is
-impossible, BIOS calls work in real mode only. VESA BIOS Extentions
+impossible; BIOS calls work in real mode only. VESA BIOS Extentions
X Version 2.0 are required, becauce we need a linear frame buffer.
X
X Advantages:
@@ -33,11 +33,12 @@
X Documentation/svga.txt for details.
X
X You should compile in both vgacon (for text mode) and vesafb (for
-graphics mode). Which of them takes over the console depends on
+graphics mode). Which of them takes over the console depends on
X whenever the specified mode is text or graphics.
X
X The graphic modes are NOT in the list which you get if you boot with
-vga=ask and hit return. Here are some mode numbers:
+vga=ask and hit return. The mode you wish to use is derived from the
+VESA mode number. Here are those VESA mode numbers:
X
X | 640x480 800x600 1024x768 1280x1024
X ----+-------------------------------------
@@ -46,19 +47,35 @@
X 64k | 0x111 0x114 0x117 0x11A
X 16M | 0x112 0x115 0x118 0x11B
X
-This are the VESA mode numbers. The video mode select code expects
-0x200 + VESA mode number. Therefore you have to enter "305" at the
-"vga=ask" prompt to boot into 1024x768x8.
-
-If this does'nt work, this might be becauce your BIOS does not support
-linear framebuffers or becauce it does'nt support this mode at all.
-Even if your board does, it might be the BIOS does not. VESA BIOS
-Extentions v2.0 are required, 1.2 is NOT sufficient. You'll get a
-"bad mode number" message if something goes wrong.
+The video mode number of the Linux kernel is the VESA mode number plus
+0x200.
+
+ Linux_kernel_mode_number = VESA_mode_number + 0x200
+
+So the table for the Kernel mode numbers are:
X
-Note: LILO can't handle hex, for booting directly with "vga=mode-number"
- you have to transform the numbers to decimal.
+ | 640x480 800x600 1024x768 1280x1024
+----+-------------------------------------
+256 | 0x301 0x303 0x305 0x307
+32k | 0x310 0x313 0x316 0x319
+64k | 0x311 0x314 0x317 0x31A
+16M | 0x312 0x315 0x318 0x31B
+
+To enable one of those modes you have to specify "vga=ask" in the
+lilo.conf file and rerun LILO. Then you can type in the descired
+mode at the "vga=ask" prompt. For example if you like to use
+1024x768x256 colors you have to say "305" at this prompt.
+
+If this does not work, this might be becauce your BIOS does not support
+linear framebuffers or becauce it does not support this mode at all.
+Even if your board does, it might be the BIOS which does not. VESA BIOS
+Extentions v2.0 are required, 1.2 is NOT sufficient. You will get a
+"bad mode number" message if something goes wrong.
X
+1. Note: LILO cannot handle hex, for booting directly with
+ "vga=mode-number" you have to transform the numbers to decimal.
+2. Note: Some newer versions of LILO appear to work with those hex values,
+ if you set the 0x infront of the numbers.
X
X X11
X ===
@@ -68,7 +85,7 @@
X It depends on X-Server and graphics board.
X
X The X-Server must restore the video mode correctly, else you end up
-with a broken console (and vesafb can't do anything about this).
+with a broken console (and vesafb cannot do anything about this).
X
X
X Configuration
@@ -98,3 +115,6 @@
X
X --
X Gerd Knorr <kra...@cs.tu-berlin.de>
+
+Minor (mostly typo) changes
+by Nico Schmoigl <schm...@rumms.uni-mannheim.de>
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/logo.txt linux/Documentation/logo.txt
--- v2.2.0-pre7/linux/Documentation/logo.txt Sun Jun 9 08:01:04 1996
+++ linux/Documentation/logo.txt Thu Jan 14 22:53:02 1999
@@ -1,6 +1,6 @@
X This is the full-colour version of the currently unofficial Linux logo
X ("currently unofficial" just means that there has been no paperwork and
-that I haven't really announced it yet). It was created by Larry Ewing,
+that I have not really announced it yet). It was created by Larry Ewing,
X and is freely usable as long as you acknowledge Larry as the original
X artist.
X
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/sound/OPL3-SA2 linux/Documentation/sound/OPL3-SA2
--- v2.2.0-pre7/linux/Documentation/sound/OPL3-SA2 Fri Jan 8 22:35:59 1999
+++ linux/Documentation/sound/OPL3-SA2 Thu Jan 14 22:53:02 1999
@@ -2,7 +2,7 @@
X ---------------------------------------------------------------
X
X Scott Murray, sco...@interlog.com
-January 5, 1998
+January 5, 1999
X
X NOTE: All trade-marked terms mentioned below are properties of their
X respective owners.
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/sound/README.OSS linux/Documentation/sound/README.OSS
--- v2.2.0-pre7/linux/Documentation/sound/README.OSS Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/README.OSS Sun Jan 17 18:23:01 1999
@@ -0,0 +1,1484 @@
+Introduction
+------------
+
+This file is a collection of all the old Readme files distributed with
+OSS/Lite by Hannu Savolainen. Since the new Linux sound driver is founded
+on it I think these information may still be interesting for users that
+have to configure their sound system.
+
+Be warned: Alan Cox is the current maintainer of the Linux sound driver so if
+you have problems with it, please contact him or the current device-specific
+driver maintainer (e.g. for aedsp16 specific problems contact me). If you have
+patches, contributions or suggestions send them to Alan: I'm sure they are
+welcome.
+
+In this document you will find a lot of references about OSS/Lite or ossfree:
+they are gone forever. Keeping this in mind and with a grain of salt this
+document can be still interesting and very helpful.
+
+[ File edited 17.01.1999 - Riccardo Facchetti ]
+
+OSS/Free version 3.8 release notes
+----------------------------------
+
+Please read the SOUND-HOWTO (available from sunsite.unc.edu and other Linux FTP
+sites). It gives instructions about using sound with Linux. It's bit out of
+date but still very useful. Information about bug fixes and such things
+is available from the web page (see above).
+
+Please check http://www.opensound.com/pguide for more info about programming
+with OSS API.
+
+ ====================================================
+- THIS VERSION ____REQUIRES____ Linux 2.1.57 OR LATER.
+ ====================================================
+
+Packages "snd-util-3.8.tar.gz" and "snd-data-0.1.tar.Z"
+contain useful utilities to be used with this driver.
+See http://www.opensound.com/ossfree/getting.html for
+download instructions.
+
+If you are looking for the installation instructions, please
+look forward into this document.
+
+Supported sound cards
+---------------------
+
+See below.
+
+Contributors
+------------
+
+This driver contains code by several contributors. In addition several other
+persons have given useful suggestions. The following is a list of major
+contributors. (I could have forgotten some names.)
+
+ Craig Metz 1/2 of the PAS16 Mixer and PCM support
+ Rob Hooft Volume computation algorithm for the FM synth.
+ Mika Liljeberg uLaw encoding and decoding routines
+ Jeff Tranter Linux SOUND HOWTO document
+ Greg Lee Volume computation algorithm for the GUS and
+ lot's of valuable suggestions.
+ Andy Warner ISC port
+ Jim Lowe,
+ Amancio Hasty Jr FreeBSD/NetBSD port
+ Anders Baekgaard Bug hunting and valuable suggestions.
+ Joerg Schubert SB16 DSP support (initial version).
+ Andrew Robinson Improvements to the GUS driver
+ Megens SA MIDI recording for SB and SB Pro (initial version).
+ Mikael Nordqvist Linear volume support for GUS and
+ nonblocking /dev/sequencer.
+ Ian Hartas SVR4.2 port
+ Markus Aroharju and
+ Risto Kankkunen Major contributions to the mixer support
+ of GUS v3.7.
+ Hunyue Yau Mixer support for SG NX Pro.
+ Marc Hoffman PSS support (initial version).
+ Rainer Vranken Initialization for Jazz16 (initial version).
+ Peter Trattler Initial version of loadable module support for Linux.
+ JRA Gibson 16 bit mode for Jazz16 (initial version)
+ Davor Jadrijevic MAD16 support (initial version)
+ Gregor Hoffleit Mozart support (initial version)
+ Riccardo Facchetti Audio Excel DSP 16 (aedsp16) support
+ James Hightower Spotting a tiny but important bug in CS423x support.
+ Denis Sablic OPTi 82C924 spesific enhancements (non PnP mode)
+ Tim MacKenzie Full duplex support for OPTi 82C930.
+
+ Please look at lowlevel/README for more contributors.
+
+There are probably many other names missing. If you have sent me some
+patches and your name is not in the above list, please inform me.
+
+Sending your contributions or patches
+-------------------------------------
+
+First of all it's highly recommended to contact me before sending anything
+or before even starting to do any work. Tell me what you suggest to be
+changed or what you have planned to do. Also ensure you are using the
+very latest (development) version of OSS/Free since the change may already be
+implemented there. In general it's major waste of time to try to improve
+several months old version. Information about the latest version can be found
+from http://www.opensound.com/ossfree. In general there is no point in
+sending me patches relative to production kernels.
+
+Sponsors etc.
+-------------
+
+The following companies have greatly helped development of this driver
+in form of a free copy of their product:
+
+Novell, Inc. UnixWare personal edition + SDK
+The Santa Cruz Operation, Inc. A SCO OpenServer + SDK
+Ensoniq Corp, a SoundScape card and extensive amount of assistance
+MediaTrix Peripherals Inc, a AudioTrix Pro card + SDK
+Acer, Inc. a pair of AcerMagic S23 cards.
+
+In addition the following companies have provided me sufficient amount
+of technical information at least some of their products (free or $$$):
+
+Advanced Gravis Computer Technology Ltd.
+Media Vision Inc.
+Analog Devices Inc.
+Logitech Inc.
+Aztech Labs Inc.
+Crystal Semiconductor Corporation,
+Integrated Circuit Systems Inc.
+OAK Technology
+OPTi
+Turtle Beach
+miro
+Ad Lib Inc. ($$)
+Music Quest Inc. ($$)
+Creative Labs ($$$)
+
+If you have some problems
+=========================
+
+Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
+Also look at the home page (http://www.opensound.com/ossfree). It may
+contain info about some recent bug fixes.
+
+It's likely that you have some problems when trying to use the sound driver
+first time. Sound cards don't have standard configuration so there are no
+good default configuration to use. Please try to use same I/O, DMA and IRQ
+values for the sound card than with DOS.
+
+If you get an error message when trying to use the driver, please look
+at /var/adm/messages for more verbose error message.
+
+
+In general the easiest way to diagnose problems is to do "cat /dev/sndstat".
+
+If you get an error message, there are some problems with the driver setup:
+
+ - "No such file or directory" tells that the device files for
+ the sound driver are missing. Use the script at the end of
+ linux/drivers/sound/Readme.linux to create them.
+
+ - "No such device" tells that the sound driver is not in the kernel.
+ You have to reconfigure and recompile the kernel to have the sound
+ driver. Compiling the driver doesn't help alone. You have to boot
+ with the newly compiled one before the driver becomes active.
+ The Linux-HOWTO should help in this step.
+
+The following errors are likely with /dev/dsp and /dev/audio.
+
+ - "No such device or address". This error message should not happen
+ with /dev/sndstat but it's possible with the other sound devices.
+ This error indicates that there are no suitable hardware for the
+ device file or the sound driver has been compiled without support for
+ this particular device. For example /dev/audio and /dev/dsp will not
+ work if "digitized voice support" was not enabled during "make config".
+
+ - "Device or resource busy". Probably the IRQ (or DMA) channel
+ required by the sound card is in use by some other device/driver.
+
+ - "I/O error". Almost certainly (99%) it's an IRQ or DMA conflict.
+ Look at the kernel messages in /var/adm/notice for more info.
+
+ - "Invalid argument". The application is calling ioctl()
+ with impossible parameters. Check that the application is
+ for sound driver version 2.X or later.
+
+In general the printout of /dev/sndstat should tell what is the problem.
+It's possible that there are bugs in the sound driver but 99% of the problems
+reported to me are caused by somehow incorrect setup during "make config".
+
+Linux installation
+==================
+
+IMPORTANT! Read this if you are installing a separately
+ distributed version of this driver.
+
+ Check that your kernel version works with this
+ release of the driver (see Readme). Also verify
+ that your current kernel version doesn't have more
+ recent sound driver version than this one. IT'S HIGHLY
+ RECOMMENDED THAT YOU USE THE SOUND DRIVER VERSION THAT
+ IS DISTRIBUTED WITH KERNEL SOURCES.
+
+- When installing separately distributed sound driver you should first
+ read the above notice. Then try to find proper directory where and how
+ to install the driver sources. You should not try to install a separately
+ distributed driver version if you are not able to find the proper way
+ yourself (in this case use the version that is distributed with kernel
+ sources). Remove old version of linux/drivers/sound directory before
+ installing new files.
+
+- To build the device files you need to run the enclosed shell script
+ (see below). You need to do this only when installing sound driver
+ first time or when upgrading to much recent version than the earlier
+ one.
+
+- Configure and compile Linux as normally (remember to include the
+ sound support during "make config"). Please refer to kernel documentation
+ for instructions about configuring and compiling kernel. File Readme.cards
+ contains card specific instructions for configuring this driver for
+ use with various sound cards.
+
+Boot time configuration (using lilo and insmod)
+-----------------------------------------------
+
+This information has been removed. Too many users didn't believe
+that it's really not necessary to use this method. Please look at
+Readme of sound driver version 3.0.1 if you still want to use this method.
+
+Problems
+--------
+
+If you have any kind of problems, there is a debugging feature which
+could help you to solve the problem. To use it, just execute the
+command:
+
+ cat /dev/sndstat
+
+and look at the output. It should display some useful info about the
+driver configuration. If there is no /dev/sndstat
+(/dev/sndstat: No such file or directory), ensure that you have executed the
+soundinstall script (at the end of this file).
+
+Common error messages:
+
+- /dev/???????: No such file or directory.
+Run the script at the end of this file.
+
+- /dev/???????: No such device.
+You are not running kernel which contains the sound driver. When using
+modularized sound driver this error means that the sound driver is not
+loaded.
+
+- /dev/????: No such device or address.
+Sound driver didn't detect suitable card when initializing. Please look at
+Readme.cards for info about configuring the driver with your card. Also
+check for possible boot (insmod) time error messages in /var/adm/messages.
+
+- Other messages or problems
+Please check http://www.opensound.com/ossfree for more info.
+
+Configuring version 3.8 (for Linux) with some common sound cards
+================================================================
+
+This document describes configuring sound cards with the freeware version of
+Open Sound Systems (OSS/Free). Information about the commercial version
+(OSS/Linux) and its configuration is available from
+http://www.opensound.com/linux.html. Information presented here is
+not valid for OSS/Linux.
+
+If you are unsure about how to configure OSS/Free
+you can download the free evaluation version of OSS/Linux from the above
+address. There is a chance that it can autodetect your sound card. In this case
+you can use the information included in soundon.log when configuring OSS/Free.
+
+
+IMPORTANT! This document covers only cards that were "known" when
+ this driver version was released. Please look at
+ http://www.opensound.com/ossfree for info about
+ cards introduced recently.
+
+ When configuring the sound driver, you should carefully
+ check each sound configuration option (particularly
+ "Support for /dev/dsp and /dev/audio"). The default values
+ offered by these programs are not necessarily valid.
+
+
+THE BIGGEST MISTAKES YOU CAN MAKE
+=================================
+
+1. Assuming that the card is Sound Blaster compatible when it's not.
+--------------------------------------------------------------------
+
+The number one mistake is to assume that your card is compatible with
+Sound Blaster. Only the cards made by Creative Technology or which have
+one or more chips labeled by Creative are SB compatible. In addition there
+are few sound chipsets which are SB compatible in Linux such as ESS1688 or
+Jazz16. Note that SB compatibility in DOS/Windows does _NOT_ mean anything
+in Linux.
+
+IF YOU REALLY ARE 150% SURE YOU HAVE A SOUND BLASTER YOU CAN SKIP THE REST OF
+THIS CHAPTER.
+
+For most other "supposed to be SB compatible" cards you have to use other
+than SB drivers (see below). It is possible to get most sound cards to work
+in SB mode but in general it's a complete waste of time. There are several
+problems which you will encounter by using SB mode with cards that are not
+truly SB compatible:
+
+- The SB emulation is at most SB Pro (DSP version 3.x) which means that
+you get only 8 bit audio (there is always an another ("native") mode which
+gives the 16 bit capability). The 8 bit only operation is the reason why
+many users claim that sound quality in Linux is much worse than in DOS.
+In addition some applications require 16 bit mode and they produce just
+noise with a 8 bit only device.
+- The card may work only in some cases but refuse to work most of the
+time. The SB compatible mode always requires special initialization which is
+done by the DOS/Windows drivers. This kind of cards work in Linux after
+you have warm booted it after DOS but they don't work after cold boot
+(power on or reset).
+- You get the famous "DMA timed out" messages. Usually all SB clones have
+software selectable IRQ and DMA settings. If the (power on default) values
+currently used by the card don't match configuration of the driver you will
+get the above error message whenever you try to record or play. There are
+few other reasons to the DMA timeout message but using the SB mode seems
+to be the most common cause.
+
+2. Trying to use a PnP (Plug & Play) card just like an ordinary sound card
+--------------------------------------------------------------------------
+
+Plug & Play is a protocol defined by Intel and Microsoft. It lets operating
+systems to easily identify and reconfigure I/O ports, IRQs and DMAs of ISA
+cards. The problem with PnP cards is that the standard Linux doesn't currently
+(versions 2.1.x and earlier) don't support PnP. This means that you will have
+to use some special tricks (see later) to get a PnP card alive. Many PnP cards
+work after they have been initialized but this is not always the case.
+
+There are sometimes both PnP and non-PnP versions of the same sound card.
+The non-PnP version is the original model which usually has been discontinued
+more than an year ago. The PnP version has the same name but with "PnP"
+appended to it (sometimes not). This causes major confusion since the non-PnP
+model works with Linux but the PnP one doesn't.
+
+You should carefully check if "Plug & Play" or "PnP" is mentioned in the name
+of the card or in the documentation or package that came with the card.
+Everything described in the rest of this document is not necessarily valid for
+PnP models of sound cards even you have managed to wake up the card properly.
+Many PnP cards are simply too different from their non-PnP ancestors which are
+covered by this document.
+
+
+Cards that are not (fully) supported by this driver
+===================================================
+
+See http://www.opensound.com/ossfree for information about sound cards
+to be supported in future.
+
+
+How to use sound without recompiling kernel and/or sound driver
+===============================================================
+
+There is a commercial sound driver which comes in precompiled form and doesn't
+require recompiling of the kernel. See http://www.4Front-tech.com/oss.html for
+more info.
+
+
+Configuring PnP cards
+=====================
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi
echo 'End of part 01'
echo 'File patch-2.2.0-pre8 is continued in part 02'
echo 02 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part02

#!/bin/sh
# this is part 02 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh

# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 02; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'


sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

+
+New versions of most sound cards use the so-called ISA PnP protocol for
+soft configuring their I/O, IRQ, DMA and shared memory resources.
+Currently at least cards made by Creative Technology (SB32 and SB32AWE
+PnP), Gravis (GUS PnP and GUS PnP Pro), Ensoniq (Soundscape PnP) and
+Aztech (some Sound Galaxy models) use PnP technology. The CS4232/4236 audio
+chip by Crystal Semiconductor (Intel Atlantis, HP Pavilion and many other
+motherboards) is also based on PnP technology but there is a "native" driver
+available for it (see information about CS4232 later in this document).
+
+PnP sound cards (as well as most other PnP ISA cards) are not supported
+by this version of the driver . Proper
+support for them should be released during 97 once the kernel level
+PnP support is available.
+
+There is a method to get most of the PnP cards to work. The basic method
+is the following:
+
+1) Boot DOS so the card's DOS drivers have a chance to initialize it.
+2) _Cold_ boot to Linux by using "loadlin.exe". Hitting ctrl-alt-del
+works with older machines but causes a hard reset of all cards on recent
+(Pentium) machines.
+3) If you have the sound driver in Linux configured properly, the card should
+work now. "Proper" means that I/O, IRQ and DMA settings are the same as in
+DOS. The hard part is to find which settings were used. See the documentation of
+your card for more info.
+
+Windows 95 could work as well as DOS but running loadlin may be difficult.
+Probably you should "shut down" your machine to MS-DOS mode before running it.
+
+Some machines have a BIOS utility for setting PnP resources. This is a good
+way to configure some cards. In this case you don't need to boot DOS/Win95
+before starting Linux.
+
+Another way to initialize PnP cards without DOS/Win95 is a Linux based
+PnP isolation tool. When writing this there is a pre alpha test version
+of such a tool available from ftp://ftp.demon.co.uk/pub/unix/linux/utils. The
+file is called isapnptools-*. Please note that this tool is just a temporary
+solution which may be incompatible with future kernel versions having proper
+support for PnP cards. There are bugs in setting DMA channels in earlier
+versions of isapnptools so at least version 1.6 is required with sound cards.
+
+Yet another way to use PnP cards is to use (commercial) OSS/Linux drivers. See
+http://www.opensound.com/linux.html for more info. This is probably the way you
+should do it if you don't want to spend time recompiling the kernel and
+required tools.
+
+
+Read this before trying to configure the driver
+===============================================
+
+There are currently many cards that work with this driver. Some of the cards
+have native support while others work since they emulate some other
+card (usually SB, MSS/WSS and/or MPU401). The following cards have native
+support in the driver. Detailed instructions for configuring these cards
+will be given later in this document.
+
+Pro Audio Spectrum 16 (PAS16) and compatibles:
+ Pro Audio Spectrum 16
+ Pro Audio Studio 16
+ Logitech Sound Man 16
+ NOTE! The original Pro Audio Spectrum as well as the PAS+ are not
+ and will not be supported by the driver.
+
+Media Vision Jazz16 based cards
+ Pro Sonic 16
+ Logitech SoundMan Wave
+ (Other Jazz based cards should work but I don't have any reports
+ about them).
+
+Sound Blasters
+ SB 1.0 to 2.0
+ SB Pro
+ SB 16
+ SB32/64/AWE
+ Configure SB32/64/AWE just like SB16. See lowlevel/README.awe
+ for information about using the wave table synth.
+ NOTE! AWE63/Gold and 16/32/AWE "PnP" cards need to be activated
+ using isapnptools before they work with OSS/Free.
+ SB16 compatible cards by other manufacturers than Creative.
+ You have been fooled since there are _no_ SB16 compatible
+ cards on the market (as of May 1997). It's likely that your card
+ is compatible just with SB Pro but there is also a non-SB-
+ compatible 16 bit mode. Usually it's MSS/WSS but it could also
+ be a proprietary one like MV Jazz16 or ESS ES688. OPTi
+ MAD16 chips are very common in so called "SB 16 bit cards"
+ (try with the MAD16 driver).
+
+ ======================================================================
+ "Supposed to be SB compatible" cards.
+ Forget the SB compatibility and check for other alternatives
+ first. The only cards that work with the SB driver in
+ Linux have been made by Creative Technology (there is at least
+ one chip on the card with "CREATIVE" printed on it). The
+ only other SB compatible chips are ESS and Jazz16 chips
+ (maybe ALSxxx chips too but they probably don't work).
+ Most other "16 bit SB compatible" cards such as "OPTi/MAD16" or
+ "Crystal" are _NOT_ SB compatible in Linux.
+
+ Practically all sound cards have some kind of SB emulation mode
+ in addition to their native (16 bit) mode. In most cases this
+ (8 bit only) SB compatible mode doesn't work with Linux. If
+ you get it working it may cause problems with games and
+ applications which require 16 bit audio. Some 16 bit only
+ applications don't check if the card actually supports 16 bits.
+ They just dump 16 bit data to a 8 bit card which produces just
+ noise.
+
+ In most cases the 16 bit native mode is supported by Linux.
+ Use the SB mode with "clones" only if you don't find anything
+ better from the rest of this doc.
+ ======================================================================
+
+Gravis Ultrasound (GUS)
+ GUS
+ GUS + the 16 bit option
+ GUS MAX
+ GUS ACE (No MIDI port and audio recording)
+ GUS PnP (with RAM)
+
+MPU-401 and compatibles
+ The driver works both with the full (intelligent mode) MPU-401
+ cards (such as MPU IPC-T and MQX-32M) and with the UART only
+ dumb MIDI ports. MPU-401 is currently the most common MIDI
+ interface. Most sound cards are compatible with it. However,
+ don't enable MPU401 mode blindly. Many cards with native support
+ in the driver have their own MPU401 driver. Enabling the standard one
+ will cause a conflict with these cards. So check if your card is
+ in the list of supported cards before enabling MPU401.
+
+Windows Sound System (MSS/WSS)
+ Even when Microsoft has discontinued their own Sound System card
+ they managed to make it a standard. MSS compatible cards are based on
+ a codec chip which is easily available from at least two manufacturers
+ (AD1848 by Analog Devices and CS4231/CS4248 by Crystal Semiconductor).
+ Currently most sound cards are based on one of the MSS compatible codec
+ chips. The CS4231 is used in the high quality cards such as GUS MAX,
+ MediaTrix AudioTrix Pro and TB Tropez (GUS MAX is not MSS compatible).
+
+ Having a AD1848, CS4248 or CS4231 codec chip on the card is a good
+ sign. Even if the card is not MSS compatible, it could be easy to write
+ support for it. Note also that most MSS compatible cards
+ require special boot time initialization which may not be present
+ in the driver. Also, some MSS compatible cards have native support.
+ Enabling the MSS support with these cards is likely to
+ cause a conflict. So check if your card is listed in this file before
+ enabling the MSS support.
+
+Yamaha FM synthesizers (OPL2, OPL3 (not OPL3-SA) and OPL4)
+ Most sound cards have a FM synthesizer chip. The OPL2 is a 2
+ operator chip used in the original AdLib card. Currently it's used
+ only in the cheapest (8 bit mono) cards. The OPL3 is a 4 operator
+ FM chip which provides better sound quality and/or more available
+ voices than the OPL2. The OPL4 is a new chip that has an OPL3 and
+ a wave table synthesizer packed onto the same chip. The driver supports
+ just the OPL3 mode directly. Most cards with an OPL4 (like
+ SM Wave and AudioTrix Pro) support the OPL4 mode using MPU401
+ emulation. Writing a native OPL4 support is difficult
+ since Yamaha doesn't give information about their sample ROM chip.
+
+ Enable the generic OPL2/OPL3 FM synthesizer support if your
+ card has a FM chip made by Yamaha. Don't enable it if your card
+ has a software (TRS) based FM emulator.
+
+ ----------------------------------------------------------------
+ NOTE! OPL3-SA is different chip than the ordinary OPL3. In addition
+ to the FM synth this chip has also digital audio (WSS) and
+ MIDI (MPU401) capabilities. Support for OPL3-SA is described below.
+ ----------------------------------------------------------------
+
+Yamaha OPL3-SA1
+
+ Yamaha OPL3-SA1 (YMF701) is an audio controller chip used on some
+ (Intel) motherboards and on cheap sound cards. It should not be
+ confused with the original OPL3 chip (YMF278) which is entirely
+ different chip. OPL3-SA1 has support for MSS, MPU401 and SB Pro
+ (not used in OSS/Free) in addition to the OPL3 FM synth.
+
+ There are also chips called OPL3-SA2, OPL3-SA3, ..., OPL3SA-N. They
+ are PnP chips and will not work with the OPL3-SA1 driver. You should
+ use the standard MSS, MPU401 and OPL3 options with thses chips and to
+ activate the card using isapnptools.
+
+4Front Technologies SoftOSS
+
+ SoftOSS is a software based wave table emulation which works with
+ any 16 bit stereo sound card. Due to its nature a fast CPU is
+ required (P133 is minimum). Although SoftOSS does _not_ use MMX
+ instructions it has proven out that recent processors (which appear
+ to have MMX) perform significantly better with SoftOSS than earlier
+ ones. For example a P166MMX beats a PPro200. SoftOSS should not be used
+ on 486 or 386 machines.
+
+ The amount of CPU load caused by SoftOSS can be controlled by
+ selecting the CONFIG_SOFTOSS_RATE and CONFIG_SOFTOSS_VOICES
+ parameters properly (they will be prompted by make config). It's
+ recommended to set CONFIG_SOFTOSS_VOICES to 32. If you have a
+ P166MMX or faster (PPro200 is not faster) you can set
+ CONFIG_SOFTOSS_RATE to 44100 (kHz). However with slower systems it
+ recommended to use sampling rates around 22050 or even 16000 kHz.
+ Selecting too high values for these parameters may hang your
+ system when playing MIDI files with hight degree of polyphony
+ (number of concurrently playing notes). It's also possible to
+ decrease CONFIG_SOFTOSS_VOICES. This makes it possible to use
+ higher sampling rates. However using fewer voices decreases
+ playback quality more than decreasing the sampling rate.
+
+ SoftOSS keeps the samples loaded on the system's RAM so much RAM is
+ required. SoftOSS should never be used on machines with less than 16 MB
+ of RAM since this is potentially dangerous (you may accidently run out
+ of memory which probably crashes the machine).
+
+ SoftOSS implements the wave table API originally designed for GUS. For
+ this reason all applications designed for GUS should work (at least
+ after minor modifications). For example gmod/xgmod and playmidi -g are
+ known to work.
+
+ To work SoftOSS will require GUS compatible
+ patch files to be installed on the system (in /dos/ultrasnd/midi). You
+ can use the public domain MIDIA patchset available from several ftp
+ sites.
+
+ *********************************************************************
+ IMPORTANT NOTICE! The original patch set distributed with the Gravis
+ Ultrasound card is not in public domain (even though it's available from
+ some FTP sites). You should contact Voice Crystal (www.voicecrystal.com)
+ if you like to use these patches with SoftOSS included in OSS/Free.
+ *********************************************************************
+
+PSS based cards (AD1848 + ADSP-2115 + Echo ESC614 ASIC)
+ Analog Devices and Echo Speech have together defined a sound card
+ architecture based on the above chips. The DSP chip is used
+ for emulation of SB Pro, FM and General MIDI/MT32.
+
+ There are several cards based on this architecture. The most known
+ ones are Orchid SW32 and Cardinal DSP16.
+
+ The driver supports downloading DSP algorithms to these cards.
+
+ NOTE! You will have to use the "old" config script when configuring
+ PSS cards.
+
+MediaTrix AudioTrix Pro
+ The ATP card is built around a CS4231 codec and an OPL4 synthesizer
+ chips. The OPL4 mode is supported by a microcontroller running a
+ General MIDI emulator. There is also a SB 1.5 compatible playback mode.
+
+Ensoniq SoundScape and compatibles
+ Ensoniq has designed a sound card architecture based on the
+ OTTO synthesizer chip used in their professional MIDI synthesizers.
+ Several companies (including Ensoniq, Reveal and Spea) are selling
+ cards based on this architecture.
+
+ NOTE! The SoundScape PnP is not supported by OSS/Free. Ensoniq VIVO and
+ VIVO90 cards are not compatible with Soundscapes so the Soundscape
+ driver will not work with them. You may want to use OSS/Linux with these
+ cards.
+
+OPTi MAD16 and Mozart based cards
+ The Mozart (OAK OTI-601), MAD16 (OPTi 82C928), MAD16 Pro (OPTi 82C929),
+ OPTi 82C924/82C925 (in _non_ PnP mode) and OPTi 82C930 interface
+ chips are used in many different sound cards, including some
+ cards by Reveal miro and Turtle Beach (Tropez). The purpose of these
+ chips is to connect other audio components to the PC bus. The
+ interface chip performs address decoding for the other chips.
+ NOTE! Tropez Plus is not MAD16 but CS4232 based.
+ NOTE! MAD16 PnP cards (82C924, 82C925, 82C931) are not MAD16 compatible
+ in the PnP mode. You will have to use them in MSS mode after having
+ initialized them using isapnptools or DOS. 82C931 probably requires
+ initialization using DOS/Windows (running isapnptools is not enough).
+ It's possible to use 82C931 with OSS/Free by jumpering it to non-PnP
+ mode (provided that the card has a jumper for this). In non-PnP mode
+ 82C931 is compatible with 82C930 and should work with the MAD16 driver
+ (without need to use isapnptools or DOS to initialize it). All OPTi
+ chips are supported by OSS/Linux (both in PnP and non-PnP modes).
+
+Audio Excel DSP16
+ Support for this card was written by Riccardo Faccetti
+ (ricc...@cdc8g5.cdc.polimi.it). The AEDSP16 driver included in
+ the lowlevel/ directory. To use it you should enable the
+ "Additional low level drivers" option.
+
+Crystal CS4232 and CS4236 based cards such as AcerMagic S23, TB Tropez _Plus_ and
+ many PC motherboards (Compaq, HP, Intel, ...)
+ CS4232 is a PnP multimedia chip which contains a CS3231A codec,
+ SB and MPU401 emulations. There is support for OPL3 too.
+ Unfortunately the MPU401 mode doesn't work (I don't know how to
+ initialize it). CS4236 is an enhanced (compatible) version of CS4232.
+ NOTE! Don't ever try to use isapnptools with CS4232 since this will just
+ freeze your machine (due to chip bugs). If you have problems in getting
+ CS4232 working you could try initializing it with DOS (CS4232C.EXE) and
+ then booting Linux using loadlin. CS4232C.EXE loads a secret firmware
+ patch which is not documented by Crystal.
+
+Turtle Beach Maui and Tropez "classic"
+ This driver version supports sample, patch and program loading commands
+ described in the Maui/Tropez User's manual.
+ There is now full initialization support too. The audio side of
+ the Tropez is based on the MAD16 chip (see above).
+ NOTE! Tropez Plus is different card than Tropez "classic" and will not
+ work fully in Linux. You can get audio features working by configuring
+ the card as a CS4232 based card (above).
+
+
+Jumpers and software configuration
+==================================
+
+Some of the earliest sound cards were jumper configurable. You have to
+configure the driver use I/O, IRQ and DMA settings
+that match the jumpers. Just few 8 bit cards are fully jumper
+configurable (SB 1.x/2.x, SB Pro and clones).
+Some cards made by Aztech have an EEPROM which contains the
+config info. These cards behave much like hardware jumpered cards.
+
+Most cards have jumper for the base I/O address but other parameters
+are software configurable. Sometimes there are few other jumpers too.
+
+Latest cards are fully software configurable or they are PnP ISA
+compatible. There are no jumpers on the board.
+
+The driver handles software configurable cards automatically. Just configure
+the driver to use I/O, IRQ and DMA settings which are known to work.
+You could usually use the same values than with DOS and/or Windows.
+Using different settings is possible but not recommended since it may cause
+some trouble (for example when warm booting from an OS to another or
+when installing new hardware to the machine).
+
+Sound driver sets the soft configurable parameters of the card automatically
+during boot. Usually you don't need to run any extra initialization
+programs when booting Linux but there are some exceptions. See the
+card-specific instructions below for more info.
+
+The drawback of software configuration is that the driver needs to know
+how the card must be initialized. It cannot initialize unknown cards
+even if they are otherwise compatible with some other cards (like SB,
+MPU401 or Windows Sound System).
+
+
+What if your card was not listed above?
+=======================================
+
+The first thing to do is to look at the major IC chips on the card.
+Many of the latest sound cards are based on some standard chips. If you
+are lucky, all of them could be supported by the driver. The most common ones
+are the OPTi MAD16, Mozart, SoundScape (Ensoniq) and the PSS architectures
+listed above. Also look at the end of this file for list of unsupported
+cards and the ones which could be supported later.
+
+The last resort is to send _exact_ name and model information of the card
+to me together with a list of the major IC chips (manufactured, model) to
+me. I could then try to check if your card looks like something familiar.
+
+There are many more cards in the world than listed above. The first thing to
+do with these cards is to check if they emulate some other card or interface
+such as SB, MSS and/or MPU401. In this case there is a chance to get the
+card to work by booting DOS before starting Linux (boot DOS, hit ctrl-alt-del
+and boot Linux without hard resetting the machine). In this method the
+DOS based driver initializes the hardware to use known I/O, IRQ and DMA
+settings. If sound driver is configured to use the same settings, everything
+should work OK.
+
+
+Configuring sound driver (with Linux)
+=====================================
+
+The sound driver is currently distributed as part of the Linux kernel. The
+files are in /usr/src/linux/drivers/sound/.
+
+****************************************************************************
+* ALWAYS USE THE SOUND DRIVER VERSION WHICH IS DISTRIBUTED WITH *
+* THE KERNEL SOURCE PACKAGE YOU ARE USING. SOME ALPHA AND BETA TEST *
+* VERSIONS CAN BE INSTALLED FROM A SEPARATELY DISTRIBUTED PACKAGE *
+* BUT CHECK THAT THE PACKAGE IS NOT MUCH OLDER (OR NEWER) THAN THE *
+* KERNEL YOU ARE USING. IT'S POSSIBLE THAT THE KERNEL/DRIVER *
+* INTERFACE CHANGES BETWEEN KERNEL RELEASES WHICH MAY CAUSE SOME *
+* INCOMPATIBILITY PROBLEMS. *
+* *
+* IN CASE YOU INSTALL A SEPARATELY DISTRIBUTED SOUND DRIVER VERSION, *
+* BE SURE TO REMOVE OR RENAME THE OLD SOUND DRIVER DIRECTORY BEFORE *
+* INSTALLING THE NEW ONE. LEAVING OLD FILES TO THE SOUND DRIVER *
+* DIRECTORY _WILL_ CAUSE PROBLEMS WHEN THE DRIVER IS USED OR *
+* COMPILED. *
+****************************************************************************
+
+To configure the driver, run "make config" in the kernel source directory
+(/usr/src/linux). Answer "y" or "m" to the question about Sound card support
+(after the questions about mouse, CD-ROM, ftape, etc. support). Questions
+about options for sound will then be asked.
+
+After configuring the kernel and sound driver, run "make dep" and compile
+the kernel following instructions in the kernel README.
+
+The sound driver configuration dialog
+-------------------------------------
+
+If you already have the sound driver installed, consult a printout of
+"cat /dev/sndstat" when configuring the driver again. It gives the I/O,
+IRQ and DMA settings you used earlier.
+
+Sound configuration starts by making some yes/no questions. Be careful
+when answering to these questions since answering y to a question may
+prevent some later ones from being asked. For example don't answer y to
+the first question (PAS16) if you don't really have a PAS16. Don't enable
+more cards than you really need since they just consume memory. Also
+some drivers (like MPU401) may conflict with your SCSI controller and
+prevent kernel from booting. If you card was in the list of supported
+cards (above), please look at the card specific config instructions
+(later in this file) before starting to configure. Some cards must be
+configured in way which is not obvious.
+
+So here is the beginning of the config dialog. Answer 'y' or 'n' to these
+questions. The default answer is shown so that (y/n) means 'y' by default and
+(n/y) means 'n'. To use the default value, just hit ENTER. But be careful
+since using the default _doesn't_ guarantee anything.
+
+Note also that all questions may not be asked. The configuration program
+may disable some questions depending on the earlier choices. It may also
+select some options automatically as well.
+
+ "ProAudioSpectrum 16 support",
+ - Answer 'y'_ONLY_ if you have a Pro Audio Spectrum _16_,
+ Pro Audio Studio 16 or Logitech SoundMan 16 (be sure that
+ you read the above list correctly). Don't answer 'y' if you
+ have some other card made by Media Vision or Logitech since they
+ are not PAS16 compatible.
+ NOTE! Since 3.5-beta10 you need to enable SB support (next question)
+ if you want to use the SB emulation of PAS16. It's also possible to
+ the emulation if you want to use a true SB card together with PAS16
+ (there is another question about this that is asked later).
+ "Sound Blaster support",
+ - Answer 'y' if you have an original SB card made by Creative Labs
+ or a full 100% hardware compatible clone (like Thunderboard or
+ SM Games). If your card was in the list of supported cards (above),
+ please look at the card specific instructions later in this file
+ before answering this question. For an unknown card you may answer
+ 'y' if the card claims to be SB compatible.
+ Enable this option also with PAS16 (changed since v3.5-beta9).
+
+ Don't enable SB if you have a MAD16 or Mozart compatible card.
+
+ "Generic OPL2/OPL3 FM synthesizer support",
+ - Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
+ Answering 'y' is usually a safe and recommended choice. However some
+ cards may have software (TSR) FM emulation. Enabling FM support
+ with these cards may cause trouble. However I don't currently know
+ such cards.
+ "Gravis Ultrasound support",
+ - Answer 'y' if you have GUS or GUS MAX. Answer 'n' if you don't
+ have GUS since the GUS driver consumes much memory.
+ Currently I don't have experiences with the GUS ACE so I don't
+ know what to answer with it.
+ "MPU-401 support (NOT for SB16)",
+ - Be careful with this question. The MPU401 interface is supported
+ by almost any sound card today. However some natively supported cards
+ have their own driver for MPU401. Enabling the MPU401 option with
+ these cards will cause a conflict. Also enabling MPU401 on a system
+ that doesn't really have a MPU401 could cause some trouble. If your
+ card was in the list of supported cards (above), please look at
+ the card specific instructions later in this file.
+
+ In MOST cases this MPU401 driver should only be used with "true"
+ MIDI-only MPU401 professional cards. In most other cases there
+ is another way to get the MPU401 compatible interface of a
+ sound card to work.
+ Support for the MPU401 compatible MIDI port of SB16, ESS1688
+ and MV Jazz16 cards is included in the SB driver. Use it instead
+ of this separate MPU401 driver with these cards. As well
+ Soundscape, PSS and Maui drivers include their own MPU401
+ options.
+
+ It's safe to answer 'y' if you have a true MPU401 MIDI interface
+ card.
+ "6850 UART Midi support",
+ - It's safe to answer 'n' to this question in all cases. The 6850
+ UART interface is so rarely used.
+ "PSS (ECHO-ADI2111) support",
+ - Answer 'y' only if you have Orchid SW32, Cardinal DSP16 or some
+ other card based on the PSS chipset (AD1848 codec + ADSP-2115
+ DSP chip + Echo ESC614 ASIC CHIP).
+ "16 bit sampling option of GUS (_NOT_ GUS MAX)",
+ - Answer 'y' if you have installed the 16 bit sampling daughtercard
+ to your GUS. Answer 'n' if you have GUS MAX. Enabling this option
+ disables GUS MAX support.
+ "GUS MAX support",
+ - Answer 'y' only if you have a GUS MAX.
+ "Microsoft Sound System support",
+ - Again think carefully before answering 'y' to this question. It's
+ safe to answer 'y' in case you have the original Windows Sound
+ System card made by Microsoft or Aztech SG 16 Pro (or NX16 Pro).
+ Also you may answer 'y' in case your card was not listed earlier
+ in this file. For cards having native support in the driver, consult
+ the card specific instructions later in this file. Some drivers
+ have their own MSS support and enabling this option will cause a
+ conflict.
+ Note! The MSS driver permits configuring two DMA channels. This is a
+ "nonstandard" feature and works only with very few cards (if any).
+ In most cases the second DMA channel should be disabled or set to
+ the same channel than the first one. Trying to configure two separate
+ channels with cards that don't support this feature will prevent
+ audio (at least recording) from working.
+ "Ensoniq Soundscape support",
+ - Answer 'y' if you have a sound card based on the Ensoniq SoundScape
+ chipset. Such cards are being manufactured at least by Ensoniq,
+ Spea and Reveal (note that Reveal makes other cards also). The oldest
+ cards made by Spea don't work properly with Linux.
+ Soundscape PnP as well as Ensoniq VIVO work only with the commercial
+ OSS/Linux version.
+ "MediaTrix AudioTrix Pro support",
+ - Answer 'y' if you have the AudioTrix Pro.
+ "Support for MAD16 and/or Mozart based cards",
+ - Answer y if your card has a Mozart (OAK OTI-601) or MAD16
+ (OPTi 82C928, 82C929, 82C924/82C925 or 82C930) audio interface chip.
+ These chips are
+ currently quite common so it's possible that many no-name cards
+ have one of them. In addition the MAD16 chip is used in some
+ cards made by known manufacturers such as Turtle Beach (Tropez),
+ Reveal (some models) and Diamond (some recent models).
+ Note OPTi 82C924 and 82C925 are MAD16 compatible only in non PnP
+ mode (jumper selectable on many cards).
+ "Support for TB Maui"
+ - This enables TB Maui specific initialization. Works with TB Maui
+ and TB Tropez (may not work with Tropez Plus).
+
+
+Then the configuration program asks some y/n questions about the higher
+level services. It's recommended to answer 'y' to each of these questions.
+Answer 'n' only if you know you will not need the option.
+
+ "MIDI interface support",
+ - Answering 'n' disables /dev/midi## devices and access to any
+ MIDI ports using /dev/sequencer and /dev/music. This option
+ also affects any MPU401 and/or General MIDI compatible devices.
+ "FM synthesizer (YM3812/OPL-3) support",
+ - Answer 'y' here.
+ "/dev/sequencer support",
+ - Answering 'n' disables /dev/sequencer and /dev/music.
+
+Entering the I/O, IRQ and DMA config parameters
+-----------------------------------------------
+
+After the above questions the configuration program prompts for the
+card specific configuration information. Usually just a set of
+I/O address, IRQ and DMA numbers are asked. With some cards the program
+asks for some files to be used during initialization of the card. For example
+many cards have a DSP chip or microprocessor which must be initialized by
+downloading a program (microcode) file to the card.
+
+Instructions for answering these questions are given in the next section.
+
+
+Card specific information
+=========================
+
+This section gives additional instructions about configuring some cards.
+Please refer manual of your card for valid I/O, IRQ and DMA numbers. Using
+the same settings with DOS/Windows and Linux is recommended. Using
+different values could cause some problems when switching between
+different operating systems.
+
+Sound Blasters (the original ones by Creative)
+---------------------------------------------
+
+NOTE! Check if you have a PnP Sound Blaster (cards sold after summer 1995
+ are almost certainly PnP ones). With PnP cards you should use isapnptools
+ to activate them (see above).
+
+It's possible to configure these cards to use different I/O, IRQ and
+DMA settings. Since the possible/default settings have changed between various
+models, you have to consult manual of your card for the proper ones. It's
+a good idea to use the same values than with DOS/Windows. With SB and SB Pro
+it's the only choice. SB16 has software selectable IRQ and DMA channels but
+using different values with DOS and Linux is likely to cause troubles. The
+DOS driver is not able to reset the card properly after warm boot from Linux
+if Linux has used different IRQ or DMA values.
+
+The original (steam) Sound Blaster (versions 1.x and 2.x) use always
+DMA1. There is no way to change it.
+
+The SB16 needs two DMA channels. A 8 bit one (1 or 3) is required for
+8 bit operation and a 16 bit one (5, 6 or 7) for the 16 bit mode. In theory
+it's possible to use just one (8 bit) DMA channel by answering the 8 bit
+one when the configuration program asks for the 16 bit one. This may work
+in some systems but is likely to cause terrible noise on some other systems.
+
+It's possible to use two SB16/32/64 at the same time. To do this you should
+first configure OSS/Free for one card. Then edit local.h manually and define
+SB2_BASE, SB2_IRQ, SB2_DMA and SB2_DMA2 for the second one. You can't get
+the OPL3, MIDI and EMU8000 devices of the second card to work. If you are
+going to use two PnP Sound Blasters, ensure that they are of different model
+and have different PnP IDs. There is no way to get two cards with the same
+card ID and serial number to work. The easiest way to check this is trying
+if isapnptools can see both cards or just one.
+
+NOTE! Don't enable the SM Games option (asked by the configuration program)
+ if you are not 101% sure that your card is a Logitech Soundman Games
+ (not a SM Wave or SM16).
+
+SB Clones
+---------
+
+First of all: There are no SB16 clones. There are SB Pro clones with a
+16 bit mode which is not SB16 compatible. The most likely alternative is that
+the 16 bit mode means MSS/WSS.
+
+There are just a few fully 100% hardware SB or SB Pro compatible cards.
+I know just Thunderboard and SM Games. Other cards require some kind of
+hardware initialization before they become SB compatible. Check if your card
+was listed in the beginning of this file. In this case you should follow
+instructions for your card later in this file.
+
+For other not fully SB clones you may try initialization using DOS in
+the following way:
+
+ - Boot DOS so that the card specific driver gets run.
+ - Hit ctrl-alt-del (or use loadlin) to boot Linux. Don't
+ switch off power or press the reset button.
+ - If you use the same I/O, IRQ and DMA settings in Linux, the
+ card should work.
+
+If your card is both SB and MSS compatible, I recommend using the MSS mode.
+Most cards of this kind are not able to work in the SB and the MSS mode
+simultaneously. Using the MSS mode provides 16 bit recording and playback.
+
+ProAudioSpectrum 16 and compatibles
+-----------------------------------
+
+PAS16 has a SB emulation chip which can be used together with the native
+(16 bit) mode of the card. To enable this emulation you should configure
+the driver to have SB support too (this has been changed since version
+3.5-beta9 of this driver).
+
+With current driver versions it's also possible to use PAS16 together with
+another SB compatible card. In this case you should configure SB support
+for the other card and to disable the SB emulation of PAS16 (there is a
+separate questions about this).
+
+With PAS16 you can use two audio device files at the same time. /dev/dsp (and
+/dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and
+/dev/audio1) is connected to the SB emulation (8 bit mono only).
+
+Gravis Ultrasound
+-----------------
+
+There are many different revisions of the Ultrasound card (GUS). The
+earliest ones (pre 3.7) don't have a hardware mixer. With these cards
+the driver uses a software emulation for synth and pcm playbacks. It's
+also possible to switch some of the inputs (line in, mic) off by setting
+mixer volume of the channel level below 10%. For recording you have
+to select the channel as a recording source and to use volume above 10%.
+
+GUS 3.7 has a hardware mixer.
+
+GUS MAX and the 16 bit sampling daughtercard have a CS4231 codec chip which
+also contains a mixer.
+
+Configuring GUS is simple. Just enable the GUS support and GUS MAX or
+the 16 bit daughtercard if you have them. Note that enabling the daughter
+card disables GUS MAX driver.
+
+NOTE for owners of the 16 bit daughtercard: By default the daughtercard
+uses /dev/dsp (and /dev/audio). Command "ln -sf /dev/dsp1 /dev/dsp"
+selects the daughter card as the default device.
+
+With just the standard GUS enabled the configuration program prompts
+for the I/O, IRQ and DMA numbers for the card. Use the same values than
+with DOS.
+
+With the daughter card option enabled you will be prompted for the I/O,
+IRQ and DMA numbers for the daughter card. You have to use different I/O
+and DMA values than for the standard GUS. The daughter card permits
+simultaneous recording and playback. Use /dev/dsp (the daughtercard) for
+recording and /dev/dsp1 (GUS GF1) for playback.
+
+GUS MAX uses the same I/O address and IRQ settings than the original GUS
+(GUS MAX = GUS + a CS4231 codec). In addition an extra DMA channel may be used.
+Using two DMA channels permits simultaneous playback using two devices
+(dev/dsp0 and /dev/dsp1). The second DMA channel is required for
+full duplex audio.
+To enable the second DMA channels, give a valid DMA channel when the config
+program asks for the GUS MAX DMA (entering -1 disables the second DMA).
+Using 16 bit DMA channels (5,6 or 7) is recommended.
+
+If you have problems in recording with GUS MAX, you could try to use
+just one 8 bit DMA channel. Recording will not work with one DMA
+channel if it's a 16 bit one.
+
+Microphone input of GUS MAX is connected to mixer in little bit nonstandard
+way. There is actually two microphone volume controls. Normal "mic" controls
+only recording level. Mixer control "speaker" is used to control volume of
+microphone signal connected directly to line/speaker out. So just decrease
+volume of "speaker" if you have problems with microphone feedback.
+
+GUS ACE works too but any attempt to record or to use the MIDI port
+will fail.
+
+GUS PnP (with RAM) is partially supported but it needs to be initialized using
+DOS or isapnptools before starting the driver.
+
+MPU401 and Windows Sound System
+-------------------------------
+
+Again. Don't enable these options in case your card is listed
+somewhere else in this file.
+
+Configuring these cards is obvious (or it should be). With MSS
+you should probably enable the OPL3 synth also since
+most MSS compatible cards have it. However check that this is true
+before enabling OPL3.
+
+Sound driver supports more than one MPU401 compatible cards at the same time
+but the config program asks config info for just the first of them.
+Adding the second or third MPU interfaces must be done manually by
+editing sound/local.h (after running the config program). Add defines for
+MPU2_BASE & MPU2_IRQ (and MPU3_BASE & MPU3_IRQ) to the file.
+
+CAUTION!
+
+The default I/O base of Adaptec AHA-1542 SCSI controller is 0x330 which
+is also the default of the MPU401 driver. Don't configure the sound driver to
+use 0x330 as the MPU401 base if you have a AHA1542. The kernel will not boot
+if you make this mistake.
+
+PSS
+---
+
+Even the PSS cards are compatible with SB, MSS and MPU401, you must not
+enable these options when configuring the driver. The configuration
+program handles these options itself. (You may use the SB, MPU and MSS options
+together with PSS if you have another card on the system).
+
+The PSS driver enables MSS and MPU401 modes of the card. SB is not enabled
+since it doesn't work concurrently with MSS. The driver loads also a
+DSP algorithm which is used to for the general MIDI emulation. The
+algorithm file (.ld) is read by the config program and written to a
+file included when the pss.c is compiled. For this reason the config
+program asks if you want to download the file. Use the genmidi.ld file
+distributed with the DOS/Windows drivers of the card (don't use the mt32.ld).
+With some cards the file is called 'synth.ld'. You must have access to
+the file when configuring the driver. The easiest way is to mount the DOS
+partition containing the file with Linux.
+
+It's possible to load your own DSP algorithms and run them with the card.
+Look at the directory pss_test of snd-util-3.0.tar.gz for more info.
+
+AudioTrix Pro
+-------------
+
+You have to enable the OPL3 and SB (not SB Pro or SB16) drivers in addition
+to the native AudioTrix driver. Don't enable MSS or MPU drivers.
+
+Configuring ATP is little bit tricky since it uses so many I/O, IRQ and
+DMA numbers. Using the same values than with DOS/Win is a good idea. Don't
+attempt to use the same IRQ or DMA channels twice.
+
+The SB mode of ATP is implemented so the ATP driver just enables SB
+in the proper address. The SB driver handles the rest. You have to configure
+both the SB driver and the SB mode of ATP to use the same IRQ, DMA and I/O
+settings.
+
+Also the ATP has a microcontroller for the General MIDI emulation (OPL4).
+For this reason the driver asks for the name of a file containing the
+microcode (TRXPRO.HEX). This file is usually located in the directory
+where the DOS drivers were installed. You must have access to this file
+when configuring the driver.
+
+If you have the effects daughtercard, it must be initialized by running
+the setfx program of snd-util-3.0.tar.gz package. This step is not required
+when using the (future) binary distribution version of the driver.
+
+Ensoniq SoundScape
+------------------
+
+NOTE! The new PnP SoundScape is not supported yet. Soundscape compatible
+ cards made by Reveal don't work with Linux. They use older revision
+ of the Soundscape chipset which is not fully compatible with
+ newer cards made by Ensoniq.
+
+The SoundScape driver handles initialization of MSS and MPU supports
+itself so you don't need to enable other drivers than SoundScape
+(enable also the /dev/dsp, /dev/sequencer and MIDI supports).
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!!!!! !!!!
+!!!!! NOTE! Before version 3.5-beta6 there WERE two sets of audio !!!!
+!!!!! device files (/dev/dsp0 and /dev/dsp1). The first one WAS !!!!
+!!!!! used only for card initialization and the second for audio !!!!
+!!!!! purposes. It WAS required to change /dev/dsp (a symlink) to !!!!
+!!!!! point to /dev/dsp1. !!!!
+!!!!! !!!!
+!!!!! This is not required with OSS versions 3.5-beta6 and later !!!!
+!!!!! since there is now just one audio device file. Please !!!!
+!!!!! change /dev/dsp to point back to /dev/dsp0 if you are !!!!
+!!!!! upgrading from an earlier driver version using !!!!
+!!!!! (cd /dev;rm dsp;ln -s dsp0 dsp). !!!!
+!!!!! !!!!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+The configuration program asks one DMA channel and two interrupts. One IRQ
+and one DMA is used by the MSS codec. The second IRQ is required for the
+MPU401 mode (you have to use different IRQs for both purposes).
+There were earlier two DMA channels for SoundScape but the current driver
+version requires just one.
+
+The SoundScape card has a Motorola microcontroller which must initialized
+_after_ boot (the driver doesn't initialize it during boot).
+The initialization is done by running the 'ssinit' program which is
+distributed in the snd-util-3.0.tar.gz package. You have to edit two
+defines in the ssinit.c and then compile the program. You may run ssinit
+manually (after each boot) or add it to /etc/rc.d/rc.local.
+
+The ssinit program needs the microcode file that comes with the DOS/Windows
+driver of the card. You will need to use version 1.30.00 or later
+of the microcode file (sndscape.co0 or sndscape.co1 depending on
+your card model). THE OLD sndscape.cod WILL NOT WORK. IT WILL HANG YOUR
+MACHINE. The only way to get the new microcode file is to download
+and install the DOS/Windows driver from ftp://ftp.ensoniq.com/pub.
+
+Then you have to select the proper microcode file to use: soundscape.co0
+is the right one for most cards and sndscape.co1 is for few (older) cards
+made by Reveal and/or Spea. The driver has capability to detect the card
+version during boot. Look at the boot log messages in /var/adm/messages
+and locate the sound driver initialization message for the SoundScape
+card. If the driver displays string <Ensoniq Soundscape (old)>, you have
+an old card and you will need to use sndscape.co1. For other cards use
+soundscape.co0. New Soundscape revisions such as Elite and PnP use
+code files with higher numbers (.co2, .co3, etc.).
+
+NOTE! Ensoniq Soundscape VIVO is not compatible with other Soundscape cards.
+ Currently it's possible to use it in Linux only with OSS/Linux
+ drivers.
+
+Check /var/adm/messages after running ssinit. The driver prints
+the board version after downloading the microcode file. That version
+number must match the number in the name of the microcode file (extension).
+
+Running ssinit with a wrong version of the sndscape.co? file is not
+dangerous as long as you don't try to use a file called sndscape.cod.
+If you have initialized the card using a wrong microcode file (sounds
+are terrible), just modify ssinit.c to use another microcode file and try
+again. It's possible to use an earlier version of sndscape.co[01] but it
+may sound weird.
+
+MAD16 (Pro) and Mozart
+----------------------
+
+You need to enable just the MAD16 /Mozart support when configuring
+the driver. _Don't_ enable SB, MPU401 or MSS. However you will need the
+/dev/audio, /dev/sequencer and MIDI supports.
+
+Mozart and OPTi 82C928 (the original MAD16) chips don't support
+MPU401 mode so enter just 0 when the configuration program asks the
+MPU/MIDI I/O base. The MAD16 Pro (OPTi 82C929) and 82C930 chips have MPU401
+mode.
+
+TB Tropez is based on the 82C929 chip. It has two MIDI ports.
+The one connected to the MAD16 chip is the second one (there is a second
+MIDI connector/pins somewhere??). If you have not connected the second MIDI
+port, just disable the MIDI port of MAD16. The 'Maui' compatible synth of
+Tropez is jumper configurable and not connected to the MAD16 chip (the
+Maui driver can be used with it).
+
+Some MAD16 based cards may cause feedback, whistle or terrible noise if the
+line3 mixer channel is turned too high. This happens at least with Shuttle
+Sound System. Current driver versions set volume of line3 low enough so
+this should not be a problem.
+
+If you have a MAD16 card which have an OPL4 (FM + Wave table) synthesizer
+chip (_not_ an OPL3), you have to append a line containing #define MAD16_OPL4
+to the file linux/drivers/sound/local.h (after running make config).
+
+MAD16 cards having a CS4231 codec support full duplex mode. This mode
+can be enabled by configuring the card to use two DMA channels. Possible
+DMA channel pairs are: 0&1, 1&0 and 3&0.
+
+NOTE! Cards having an OPTi 82C924/82C925 chip work with OSS/Free only in
+non-PnP mode (usually jumper selectable). The PnP mode is supported only
+by OSS/Linux.
+
+MV Jazz (ProSonic)
+------------------
+
+The Jazz16 driver is just a hack made to the SB Pro driver. However it works
+fairly well. You have to enable SB, SB Pro (_not_ SB16) and MPU401 supports
+when configuring the driver. The configuration program asks later if you
+want support for MV Jazz16 based cards (after asking SB base address). Answer
+'y' here and the driver asks the second (16 bit) DMA channel.
+
+The Jazz16 driver uses the MPU401 driver in a way which will cause
+problems if you have another MPU401 compatible card. In this case you must
+give address of the Jazz16 based MPU401 interface when the config
+program prompts for the MPU401 information. Then look at the MPU401
+specific section for instructions about configuring more than one MPU401 cards.
+
+Logitech Soundman Wave
+----------------------
+
+Read the above MV Jazz specific instructions first.
+
+The Logitech SoundMan Wave (don't confuse this with the SM16 or SM Games) is
+a MV Jazz based card which has an additional OPL4 based wave table
+synthesizer. The OPL4 chip is handled by an on board microcontroller
+which must be initialized during boot. The config program asks if
+you have a SM Wave immediately after asking the second DMA channel of jazz16.
+If you answer 'y', the config program will ask name of the file containing
+code to be loaded to the microcontroller. The file is usually called
+MIDI0001.BIN and it's located in the DOS/Windows driver directory. The file
+may also be called as TSUNAMI.BIN or something else (older cards?).
+
+The OPL4 synth will be inaccessible without loading the microcontroller code.
+
+Also remember to enable SB MPU401 support if you want to use the OPL4 mode.
+(Don't enable the 'normal' MPU401 device as with some earlier driver
+versions (pre 3.5-alpha8)).
+
+NOTE! Don't answer 'y' when the driver asks about SM Games support
+ (the next question after the MIDI0001.BIN name). However
+ answering 'y' doesn't cause damage your computer so don't panic.
+
+Sound Galaxies
+--------------
+
+There are many different Sound Galaxy cards made by Aztech. The 8 bit
+ones are fully SB or SB Pro compatible and there should be no problems
+with them.
+
+The older 16 bit cards (SG Pro16, SG NX Pro16, Nova and Lyra) have
+an EEPROM chip for storing the configuration data. There is a microcontroller
+which initializes the card to match the EEPROM settings when the machine
+is powered on. These cards actually behave just like they have jumpers
+for all of the settings. Configure driver for MSS, MPU, SB/SB Pro and OPL3
+supports with these cards.
+
+There are some new Sound Galaxies in the market. I have no experience with
+them so read the card's manual carefully.
+
+ESS ES1688 and ES688 'AudioDrive' based cards
+---------------------------------------------
+
+Support for these two ESS chips is embedded in the SB driver.
+Configure these cards just like SB. Enable the 'SB MPU401 MIDI port'
+if you want to use MIDI features of ES1688. ES688 doesn't have MPU mode
+so you don't need to enable it (the driver uses normal SB MIDI automatically
+with ES688).
+
+NOTE! ESS cards are not compatible with MSS/WSS so don't worry if MSS support
+of OSS doesn't work with it.
+
+There are some ES1688/688 based sound cards and (particularily) motherboards
+which use software configurable I/O port relocation feature of the chip.
+This ESS proprietary feature is supported only by OSS/Linux.
+
+There are ES1688 based cards which use different interrupt pin assignment than
+recommended by ESS (5, 7, 9/2 and 10). In this case all IRQ's don't work.
+At least a card called (Pearl?) Hypersound 16 supports IRQ15 but it doesn't
+work.
+
+ES1868 is a PnP chip which is (supposed to be) compatible with ESS1688
+brobably works with OSS/Free after initialization using isapnptools.
+
+Reveal cards
+------------
+
+There are several different cards made/marketed by Reveal. Some of them
+are compatible with SoundScape and some use the MAD16 chip. You may have
+to look at the card and try to identify its origin.
+
+Diamond
+-------
+
+The oldest (Sierra Aria based) sound cards made by Diamond are not supported
+(they may work if the card is initialized using DOS). The recent (LX?)
+models are based on the MAD16 chip which is supported by the driver.
+
+Audio Excel DSP16
+-----------------
+
+Support for this card is currently not functional. A new driver for it
+should be available later this year.
+
+PCMCIA cards
+------------
+
+Sorry, can't help. Some cards may work and some don't.
+
+TI TM4000M notebooks
+--------------------
+
+These computers have a built in sound support based on the Jazz chipset.
+Look at the instructions for MV Jazz (above). It's also important to note
+that there is something wrong with the mouse port and sound at least on
+some TM models. Don't enable the "C&T 82C710 mouse port support" when
+configuring Linux. Having it enabled is likely to cause mysterious problems
+and kernel failures when sound is used.
+
+miroSOUND
+---------
+
+The miroSOUND PCM12 has been used successfully. This card is based on
+the MAD16, OPL4, and CS4231A chips and everything said in the section
+about MAD16 cards applies here, too. The only major difference between
+the PCM12 and other MAD16 cards is that instead of the mixer in the
+CS4231 codec a separate mixer controlled by an on-board 80C32
+microcontroller is used. Control of the mixer takes place via the ACI
+(miro's audio control interface) protocol that is implemented in a
+separate lowlevel driver. Make sure you compile this ACI driver
+together with the normal MAD16 support when you use a miroSOUND PCM12
+card. The ACI mixer is controlled by /dev/mixer and the CS4231 mixer
+by /dev/mixer2. You usually don't want to change anything on the
+CS4231 mixer.
+
+The miroSOUND PCM12 is capable of full duplex operation (simultaneous
+PCM replay and recording), which allows you to implement nice
+real-time signal processing audio effect software and network
+telephones. The ACI mixer has to be configured into a special "solo"
+mode for duplex operation in order to avoid feedback caused by the
+mixer (input hears output signal). See lowlevel/aci.c for details on
+the ioctl() for activating the "solo" mode.
+
+The following configuration parameters have worked fine for the PCM12
+in Markus Kuhn's system, many other configurations might work, too:
+CONFIG_MAD16_BASE=0x530, CONFIG_MAD16_IRQ=11, CONFIG_MAD16_DMA=3,
+CONFIG_MAD16_DMA2=0, CONFIG_MAD16_MPU_BASE=0x330, CONFIG_MAD16_MPU_IRQ=10,
+DSP_BUFFSIZE=65536, SELECTED_SOUND_OPTIONS=0x00281000.
+
+The miroSOUND PCM1 pro and the PCM20 are very similar to the PCM12.
+Perhaps the same ACI driver also works for these cards, however this
+has never actually been tested. The PCM20 contains a radio tuner,
+which is also controlled by ACI. This radio tuner is currently not
+supported by the ACI driver, but documentation for it was provided by
+miro and ACI tuner support could easily be added if someone is really
+interested.
+
+Compaq Deskpro XL
+-----------------
+
+The builtin sound hardware of Compaq Deskpro XL is now supported.
+You need to configure the driver with MSS and OPL3 supports enabled.
+In addition you need to manually edit linux/drivers/sound/local.h and
+to add a line containing "#define DESKPROXL" if you used
+make menuconfig/xconfig.
+
+Others?
+-------
+
+Since there are so many different sound cards, it's likely that I have
+forgotten to mention many of them. Please inform me if you know yet another
+card which works with Linux, please inform me (or is anybody else
+willing to maintain a database of supported cards (just like in XF86)?).
+
+Cards not supported yet
+=======================
+
+Please check the version of sound driver you are using before
+complaining that your card is not supported. It's possible you are
+using a driver version which was released months before your card was
+introduced. The driver's release date is listed after its version number in a
+"cat /dev/sndstat" printout and in the file linux/drivers/sound/soundvers.h.
+
+First of all, there is an easy way to make most sound cards work with Linux.
+Just use the DOS based driver to initialize the card to a known state, then use
+loadlin.exe to boot Linux. If Linux is configured to use the same I/O, IRQ and
+DMA numbers as DOS, the card could work.
+(ctrl-alt-del can be used in place of loadlin.exe but it doesn't work with
+new motherboards). This method works also with all/most PnP sound cards.
+
+Don't get fooled with SB compatibility. Most cards are compatible with
+SB but that may require a TSR which is not possible with Linux. If
+the card is compatible with MSS, it's a better choice. Some cards
+don't work in the SB and MSS modes at the same time.
+
+Then there are cards which are no longer manufactured and/or which
+are relatively rarely used (such as the 8 bit ProAudioSpectrum
+models). It's extremely unlikely that such cards ever get supported.
+Adding support for a new card requires much work and increases time
+required in maintaining the driver (some changes need to be done
+to all low level drivers and be tested too, maybe with multiple
+operating systems). For this reason I have made a decision to not support
+obsolete cards. It's possible that someone else makes a separately
+distributed driver (diffs) for the card.
+
+Writing a driver for a new card is not possible if there are no
+programming information available about the card. If you don't
+find your new card from this file, look from the home page
+(http://www.opensound.com/ossfree). Then please contact
+manufacturer of the card and ask if they have (or are willing to)
+released technical details of the card. Do this before contacting me. I
+can only answer 'no' if there are no programming information available.
+
+I have made decision to not accept code based on reverse engineering
+to the driver. There are three main reasons: First I don't want to break
+relationships to sound card manufacturers. The second reason is that
+maintaining and supporting a driver without any specs will be a pain.
+The third reason is that companies have freedom to refuse selling their
+products to other than Windows users.
+
+Some companies don't give low level technical information about their
+products to public or at least their require signing a NDA. It's not
+possible to implement a freeware driver for them. However it's possible
+that support for such cards become available in the commercial version
+of this driver (see http://www.4Front-tech.com/oss.html for more info).
+
+There are some common audio chipsets that are not supported yet. For example
+Sierra Aria and IBM Mwave. It's possible that these architectures
+get some support in future but I can't make any promises. Just look
+at the home page (http://www.opensound.com/ossfree/new_cards.html)
+for latest info.
+
+Information about unsupported sound cards and chipsets is welcome as well
+as free copies of sound cards, SDKs and operating systems.
+
+If you have any corrections and/or comments, please contact me.
+
+Hannu Savolainen
+ha...@opensound.com
+
+Personal home page: http://www.compusonic.fi/~hannu
+home page of OSS/Free: http://www.opensound.com/ossfree
+
+home page of commercial OSS
+(Open Sound System) drivers: http://www.opensound.com/oss.html
diff -u --recursive --new-file v2.2.0-pre7/linux/Documentation/sound/README.modules linux/Documentation/sound/README.modules
--- v2.2.0-pre7/linux/Documentation/sound/README.modules Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/README.modules Sun Jan 17 18:23:01 1999
@@ -0,0 +1,99 @@
+Building a modular sound driver
+================================
+
+ The following information is current as of linux-2.1.85. Check the other
+readme files, especially README.OSS, for information not specific to
+making sound modular.
+
+ First, configure your kernel. This is an idea of what you should be
+setting in the sound section:
+
+<M> Sound card support
+
+<M> 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support
+
+ I have SoundBlaster. Select your card from the list.
+
+<M> Generic OPL2/OPL3 FM synthesizer support
+<M> FM synthesizer (YM3812/OPL-3) support
+
+ If you don't set these, you will probably find you can play .wav files
+but not .midi. As the help for them says, set them unless you know your
+card does not use one of these chips for FM support.
+
+ Once you are configured, make zlilo, modules, modules_install; reboot.
+Note that it is no longer necessary or possible to configure sound in the
+drivers/sound dir. Now one simply configures and makes one's kernel and
+modules in the usual way.
+
+ Then, add to your /etc/modules.conf or /etc/conf.modules something like:
+
+alias char-major-14 sb
+post-install sb /sbin/modprobe "-k" "adlib_card"
+options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
+options adlib_card io=0x388 # FM synthesizer
+
+ The effect of this is that the sound driver and all necessary bits and
+pieces autoload on demand, assuming you use kerneld (a sound choice) and
+autoclean when not in use. Also, options for the device drivers are
+set. They will not work without them. Change as appropriate for your card.
+If you are not yet using the very cool kerneld, you will have to "modprobe
+-k sb" yourself to get things going. Eventually things may be fixed so
+that this kludgery is not necessary; for the time being, it seems to work
+well.
+
+ Replace 'sb' with the driver for your card, and give it the right
+options. To find the filename of the driver, look in
+/lib/modules/<kernel-version>/misc. Mine looks like:
+
+adlib_card.o # This is the generic OPLx driver


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 02'
echo 'File patch-2.2.0-pre8 is continued in part 03'
echo 03 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part03

#!/bin/sh
# this is part 03 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 03; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

+opl3.o # The OPL3 driver
+sb.o # <<The SoundBlaster driver. Yours may differ.>>
+sound.o # The sound driver
+uart401.o # Used by sb, maybe other cards
+
+ Whichever card you have, try feeding it the options that would be the
+default if you were making the driver wired, not as modules. You can look
+at the init_module() code for the card to see what args are expected.
+
+ Note that at present there is no way to configure the io, irq and other
+parameters for the modular drivers as one does for the wired drivers.. One
+needs to pass the modules the necessary parameters as arguments, either
+with /etc/modules.conf or with command-line args to modprobe, e.g.
+
+modprobe -k sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
+modprobe -k adlib_card io=0x388
+
+ recommend using /etc/modules.conf.
+
+Persistent DMA Buffers:
+
+The sound modules normally allocate DMA buffers during open() and
+deallocate them during close(). Linux can often have problems allocating
+DMA buffers for ISA cards on machines with more than 16MB RAM. This is
+because ISA DMA buffers must exist below the 16MB boundry and it is quite
+possible that we can't find a large enough free block in this region after
+the machine has been running for any amount of time. The way to avoid this
+problem is to allocate the DMA buffers during module load and deallocate
+them when the module is unloaded. For this to be effective we need to load
+the sound modules right after the kernel boots, either manually or by an
+init script, and keep them around until we shut down. This is a little
+wasteful of RAM, but it guarantees that sound always works.
+
+To make the sound driver use persistent DMA buffers we need to pass the
+sound.o module a "dmabuf=1" command-line argument. This is normally done
+in /etc/conf.modules (or the more proper /etc/modules.conf) like so:
+
+options sound dmabuf=1
+
+If you have 16MB or less RAM or a PCI sound card, this is wasteful and
+unnecessary. It is possible that machine with 16MB or less RAM will find
+this option useful, but if your machine is so memory-starved that it
+cannot find a 64K block free, you will be wasting even more RAM by keeping
+the sound modules loaded and the DMA buffers allocated when they are not
+needed. The proper solution is to upgrade your RAM. But you do also have
+this improper solution as well. Use it wisely.
+
+ I'm afraid I know nothing about anything but my setup, being more of a
+text-mode guy anyway. If you have options for other cards or other helpful
+hints, send them to me, Jim Bray, j...@as220.org, http://as220.org/jb.
diff -u --recursive --new-file v2.2.0-pre7/linux/MAINTAINERS linux/MAINTAINERS
--- v2.2.0-pre7/linux/MAINTAINERS Thu Jan 7 15:11:35 1999
+++ linux/MAINTAINERS Mon Jan 18 12:47:33 1999
@@ -170,6 +170,12 @@
X W: http://www.dandelion.com/Linux/
X S: Maintained
X
+CONFIGURE, MENUCONFIG, XCONFIG
+P: Michael Elizabeth Chastain
+M: m...@shout.net
+L: linux-...@torque.net
+S: Maintained
+
X CONFIGURE.HELP
X P: Axel Boldt
X M: bo...@math.ucsb.edu
@@ -343,6 +349,12 @@
X M: pe...@jcu.cz
X S: Maintained
X
+IBM MCA SCSI SUBSYSTEM DRIVER
+P: Michael Lang
+M: lan...@kph.uni-mainz.de
+W: http://www.uni-mainz.de/~langm000/linux.html
+S: Maintained
+
X IDE DRIVER [GENERAL]
X P: Andre Hedrick
X M: hed...@astro.dyer.vanderbilt.edu
@@ -352,8 +364,6 @@
X IDE/ATAPI CDROM DRIVER
X P: Jens Axboe
X M: ax...@image.dk
-P: Chris Zwilling
-M: ch...@cloudnet.com
X L: linux-...@vger.rutgers.edu
X S: Maintained
X
@@ -446,12 +456,6 @@
X W: http://www.tazenda.demon.co.uk/phil/linux-hp
X S: Maintained
X
-MENUCONFIG
-P: Michael Elizabeth Chastain
-M: m...@shout.net
-L: linux-...@vger.rutgers.edu
-S: Maintained
-
X MIPS
X P: Ralf Baechle
X M: ra...@gnu.ai.mit.edu
@@ -731,8 +735,6 @@
X UNIFORM CDROM DRIVER
X P: Jens Axboe
X M: ax...@image.dk
-P: Chris Zwilling
-M: ch...@cloudnet.com
X L: linux-...@vger.rutgers.edu
X S: Maintained
X
diff -u --recursive --new-file v2.2.0-pre7/linux/Makefile linux/Makefile
--- v2.2.0-pre7/linux/Makefile Wed Jan 13 15:00:41 1999
+++ linux/Makefile Sun Jan 17 18:32:26 1999
@@ -1,7 +1,7 @@
X VERSION = 2
X PATCHLEVEL = 2
X SUBLEVEL = 0
-EXTRAVERSION =-pre7
+EXTRAVERSION =-pre8
X
X ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
X
@@ -277,7 +277,7 @@
X else \
X echo \#define LINUX_COMPILE_DOMAIN ; \
X fi >> .ver
- @echo \#define LINUX_COMPILER \"`$(CC) -v 2>&1 | tail -1`\" >> .ver
+ @echo \#define LINUX_COMPILER \"`$(CC) $(CFLAGS) -v 2>&1 | tail -1`\" >> .ver
X @mv -f .ver $@
X
X include/linux/version.h: ./Makefile
diff -u --recursive --new-file v2.2.0-pre7/linux/REPORTING-BUGS linux/REPORTING-BUGS
--- v2.2.0-pre7/linux/REPORTING-BUGS Fri Jan 8 22:36:00 1999
+++ linux/REPORTING-BUGS Thu Jan 14 22:53:02 1999
@@ -26,12 +26,12 @@
X information they're really interested in.
X
X First run the ver_linux script included as scripts/ver_linux or
-at <URL:ftp://ftp.sai.msu.su//sai2/ftp/pub/Linux/ver_linux> It checks out
+at <URL:ftp://ftp.sai.msu.su/pub/Linux/ver_linux> It checks out
X the version of some important subsystems. Run it with the commnd
X "sh scripts/ver_linux"
X
X Use that information to fill in all fields of the bug report form, and
-post it to the mailing list with a subject of "ISSUE: <one line
+post it to the mailing list with a subject of "PROBLEM: <one line
X summary from [1.]>" for easy identification by the developers
X
X [1.] One line summary of the problem:
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v2.2.0-pre7/linux/arch/alpha/Makefile Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/Makefile Sat Jan 16 17:02:50 1999
@@ -19,6 +19,10 @@
X # Determine if GCC understands the -mcpu= option.
X have_mcpu := $(shell if $(CC) -mcpu=ev5 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
X
+have_mcpu_pca56 := $(shell if $(CC) -mcpu=pca56 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
+
+have_mcpu_ev6 := $(shell if $(CC) -mcpu=ev6 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
+
X # Turn on the proper cpu optimizations.
X ifeq ($(have_mcpu),y)
X # If GENERIC, make sure to turn off any instruction set extensions that
@@ -34,8 +38,19 @@
X ifeq ($(CONFIG_ALPHA_PYXIS),y)
X CFLAGS := $(CFLAGS) -mcpu=ev56
X endif
+ ifeq ($(CONFIG_ALPHA_POLARIS),y)
+ ifeq ($(have_mcpu_pca56),y)
+ CFLAGS := $(CFLAGS) -mcpu=pca56
+ else
+ CFLAGS := $(CFLAGS) -mcpu=ev56
+ endif
+ endif
X ifeq ($(CONFIG_ALPHA_EV6),y)
- CFLAGS := $(CFLAGS) -mcpu=ev6
+ ifeq ($(have_mcpu_ev6),y)
+ CFLAGS := $(CFLAGS) -mcpu=ev6
+ else
+ CFLAGS := $(CFLAGS) -mcpu=pca56
+ endif
X endif
X endif
X
@@ -55,7 +70,7 @@
X CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWIO_ENABLED
X endif
X ifeq ($(CONFIG_ALPHA_POLARIS),y)
- CFLAGS := $(CFLAGS) -Wa,-m21164a
+ CFLAGS := $(CFLAGS) -Wa,-m21164pc
X endif
X endif
X
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.2.0-pre7/linux/arch/alpha/config.in Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/config.in Thu Jan 14 10:29:28 1999
@@ -255,8 +255,6 @@
X
X source fs/Config.in
X
-source fs/nls/Config.in
-
X if [ "$CONFIG_VT" = "y" ]; then
X mainmenu_option next_comment
X comment 'Console drivers'
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.2.0-pre7/linux/arch/alpha/kernel/alpha_ksyms.c Thu Dec 31 10:28:58 1998
+++ linux/arch/alpha/kernel/alpha_ksyms.c Sat Jan 16 17:02:50 1999
@@ -28,6 +28,7 @@
X #include <asm/irq.h>
X #include <asm/machvec.h>
X #include <asm/pgtable.h>
+#include <asm/semaphore.h>
X
X #define __KERNEL_SYSCALLS__
X #include <asm/unistd.h>
@@ -139,6 +140,13 @@
X EXPORT_SYMBOL_NOVERS(__do_clear_user);
X EXPORT_SYMBOL(__strncpy_from_user);
X EXPORT_SYMBOL(__strlen_user);
+
+/*
+ * The following are specially called from the semaphore assembly stubs.
+ */
+EXPORT_SYMBOL_NOVERS(__down_failed);
+EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
+EXPORT_SYMBOL_NOVERS(__up_wakeup);
X
X /*
X * SMP-specific symbols.
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.2.0-pre7/linux/arch/alpha/kernel/irq.c Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/kernel/irq.c Sat Jan 16 17:02:50 1999
@@ -335,9 +335,12 @@
X #ifndef __SMP__
X p += sprintf(p, "%10u ", kstat_irqs(i));
X #else
- for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
- kstat.irqs[cpu_logical_map(j)][i]);
+ {
+ int j;
+ for (j = 0; j < smp_num_cpus; j++)
+ p += sprintf(p, "%10u ",
+ kstat.irqs[cpu_logical_map(j)][i]);
+ }
X #endif
X p += sprintf(p, " %c%s",
X (action->flags & SA_INTERRUPT)?'+':' ',
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.2.0-pre7/linux/arch/alpha/kernel/process.c Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/kernel/process.c Mon Jan 18 09:55:50 1999
@@ -261,20 +261,15 @@
X {
X if (!usp)
X usp = rdusp();
- return do_fork(clone_flags & ~CLONE_VFORK, usp, (struct pt_regs *) (swstack+1));
+ return do_fork(clone_flags, usp, (struct pt_regs *) (swstack+1));
X }
X
X int alpha_vfork(struct switch_stack * swstack)
X {
X int child;
- struct semaphore sem = MUTEX_LOCKED;
X
- current->vfork_sem = &sem;
X child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
X (struct pt_regs *) (swstack+1));
-
- if (child > 0)
- down(&sem);
X
X return child;
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.2.0-pre7/linux/arch/alpha/kernel/setup.c Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/kernel/setup.c Thu Jan 14 10:21:40 1999
@@ -94,66 +94,46 @@
X * Declare all of the machine vectors.
X */
X
-extern struct alpha_machine_vector alcor_mv;
-extern struct alpha_machine_vector alphabook1_mv;
-extern struct alpha_machine_vector avanti_mv;
-extern struct alpha_machine_vector cabriolet_mv;
-extern struct alpha_machine_vector dp264_mv;
-extern struct alpha_machine_vector eb164_mv;
-extern struct alpha_machine_vector eb64p_mv;
-extern struct alpha_machine_vector eb66_mv;
-extern struct alpha_machine_vector eb66p_mv;
-extern struct alpha_machine_vector jensen_mv;
-extern struct alpha_machine_vector lx164_mv;
-extern struct alpha_machine_vector miata_mv;
-extern struct alpha_machine_vector mikasa_mv;
-extern struct alpha_machine_vector mikasa_primo_mv;
-extern struct alpha_machine_vector monet_mv;
-extern struct alpha_machine_vector webbrick_mv;
-extern struct alpha_machine_vector noname_mv;
-extern struct alpha_machine_vector noritake_mv;
-extern struct alpha_machine_vector noritake_primo_mv;
-extern struct alpha_machine_vector p2k_mv;
-extern struct alpha_machine_vector pc164_mv;
-extern struct alpha_machine_vector rawhide_mv;
-extern struct alpha_machine_vector ruffian_mv;
-extern struct alpha_machine_vector rx164_mv;
-extern struct alpha_machine_vector sable_mv;
-extern struct alpha_machine_vector sable_gamma_mv;
-extern struct alpha_machine_vector sx164_mv;
-extern struct alpha_machine_vector takara_mv;
-extern struct alpha_machine_vector xl_mv;
-extern struct alpha_machine_vector xlt_mv;
-#pragma weak alcor_mv
-#pragma weak alphabook1_mv
-#pragma weak avanti_mv
-#pragma weak cabriolet_mv
-#pragma weak dp264_mv
-#pragma weak eb164_mv
-#pragma weak eb64p_mv
-#pragma weak eb66_mv
-#pragma weak eb66p_mv
-#pragma weak jensen_mv
-#pragma weak lx164_mv
-#pragma weak miata_mv
-#pragma weak mikasa_mv
-#pragma weak mikasa_primo_mv
-#pragma weak monet_mv
-#pragma weak webbrick_mv
-#pragma weak noname_mv
-#pragma weak noritake_mv
-#pragma weak noritake_primo_mv
-#pragma weak p2k_mv
-#pragma weak pc164_mv
-#pragma weak rawhide_mv
-#pragma weak ruffian_mv
-#pragma weak rx164_mv
-#pragma weak sable_mv
-#pragma weak sable_gamma_mv
-#pragma weak sx164_mv
-#pragma weak takara_mv
-#pragma weak xl_mv
-#pragma weak xlt_mv
+/* GCC 2.7.2 (on alpha at least) is lame. It does not support either
+ __attribute__((weak)) or #pragma weak. Bypass it and talk directly
+ to the assembler. */
+
+#define WEAK(X) \
+ extern struct alpha_machine_vector X; \
+ asm(".weak "#X)
+
+WEAK(alcor_mv);
+WEAK(alphabook1_mv);
+WEAK(avanti_mv);
+WEAK(cabriolet_mv);
+WEAK(dp264_mv);
+WEAK(eb164_mv);
+WEAK(eb64p_mv);
+WEAK(eb66_mv);
+WEAK(eb66p_mv);
+WEAK(jensen_mv);
+WEAK(lx164_mv);
+WEAK(miata_mv);
+WEAK(mikasa_mv);
+WEAK(mikasa_primo_mv);
+WEAK(monet_mv);
+WEAK(noname_mv);
+WEAK(noritake_mv);
+WEAK(noritake_primo_mv);
+WEAK(p2k_mv);
+WEAK(pc164_mv);
+WEAK(rawhide_mv);
+WEAK(ruffian_mv);
+WEAK(rx164_mv);
+WEAK(sable_mv);
+WEAK(sable_gamma_mv);
+WEAK(sx164_mv);
+WEAK(takara_mv);
+WEAK(webbrick_mv);
+WEAK(xl_mv);
+WEAK(xlt_mv);
+
+#undef WEAK
X
X
X void __init
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.2.0-pre7/linux/arch/alpha/kernel/smp.c Thu Dec 31 10:28:58 1998
+++ linux/arch/alpha/kernel/smp.c Sat Jan 16 17:02:50 1999
@@ -670,7 +670,7 @@
X {
X int this_cpu = smp_processor_id();
X volatile int * pending_ipis = &ipi_bits[this_cpu];
- unsigned long ops, which;
+ unsigned long ops;
X
X DBGS(("handle_ipi: on CPU %d ops 0x%x PC 0x%lx\n",
X this_cpu, *pending_ipis, regs->pc));
@@ -716,7 +716,7 @@
X halt();
X }
X else {
- printk(KERN_CRIT "unknown_ipi() on CPU %ld: %d\n",
+ printk(KERN_CRIT "unknown_ipi() on CPU %d: %lu\n",
X this_cpu, which);
X }
X } while (ops);
@@ -894,7 +894,7 @@
X
X #else
X
-#define spinlock_raise_ipl(LOCK) ((LOCK), 0)
+#define spinlock_raise_ipl(LOCK) ((void)(LOCK), 0)
X #define spinlock_restore_ipl(PREV) ((void)(PREV))
X
X #endif /* MANAGE_SPINLOCK_IPL */
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile
--- v2.2.0-pre7/linux/arch/alpha/lib/Makefile Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/lib/Makefile Sat Jan 16 17:02:51 1999
@@ -7,7 +7,7 @@
X strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
X strchr.o strrchr.o \
X copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
- csum_ipv6_magic.o strcasecmp.o \
+ csum_ipv6_magic.o strcasecmp.o semaphore.o \
X srm_dispatch.o srm_fixup.o srm_puts.o srm_printk.o
X
X lib.a: $(OBJS)
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/alpha/lib/semaphore.S linux/arch/alpha/lib/semaphore.S
--- v2.2.0-pre7/linux/arch/alpha/lib/semaphore.S Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/lib/semaphore.S Sat Jan 16 17:02:51 1999
@@ -0,0 +1,184 @@
+/*
+ * linux/arch/alpha/lib/semaphore.S
+ *
+ * Copyright (C) 1999 Richard Henderson
+ */
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ */
+
+ .set noat
+ .set noreorder
+ .align 4
+
+/* __down_failed takes the semaphore in $24, clobbers $24 and $28. */
+
+ .globl __down_failed
+ .ent __down_failed
+__down_failed:
+ ldgp $29,0($27)
+ lda $30, -20*8($30)
+ stq $28, 0*8($30)
+ stq $0, 1*8($30)
+ stq $1, 2*8($30)
+ stq $2, 3*8($30)
+ stq $3, 4*8($30)
+ stq $4, 5*8($30)
+ stq $5, 6*8($30)
+ stq $6, 7*8($30)
+ stq $7, 8*8($30)
+ stq $16, 9*8($30)
+ stq $17, 10*8($30)
+ stq $18, 11*8($30)
+ stq $19, 12*8($30)
+ stq $20, 13*8($30)
+ stq $21, 14*8($30)
+ stq $22, 15*8($30)
+ stq $23, 16*8($30)
+ stq $25, 17*8($30)
+ stq $26, 18*8($30)
+ .frame $30, 20*8, $28
+ .prologue 1
+
+ mov $24, $16
+ jsr __down
+
+ ldq $28, 0*8($30)
+ ldq $0, 1*8($30)
+ ldq $1, 2*8($30)
+ ldq $2, 3*8($30)
+ ldq $3, 4*8($30)
+ ldq $4, 5*8($30)
+ ldq $5, 6*8($30)
+ ldq $6, 7*8($30)
+ ldq $7, 8*8($30)
+ ldq $16, 9*8($30)
+ ldq $17, 10*8($30)
+ ldq $18, 11*8($30)
+ ldq $19, 12*8($30)
+ ldq $20, 13*8($30)
+ ldq $21, 14*8($30)
+ ldq $22, 15*8($30)
+ ldq $23, 16*8($30)
+ ldq $25, 17*8($30)
+ ldq $26, 18*8($30)
+ lda $30, 20*8($30)
+ ret $31, ($28), 0
+ .end __down_failed
+
+/* __down_failed_interruptible takes the semaphore in $24,
+ clobbers $28, returns success in $24. */
+
+ .globl __down_failed_interruptible
+ .ent __down_failed_interruptible
+__down_failed_interruptible:
+ ldgp $29,0($27)
+ ldgp $29,0($27)
+ lda $30, -20*8($30)
+ stq $28, 0*8($30)
+ stq $0, 1*8($30)
+ stq $1, 2*8($30)
+ stq $2, 3*8($30)
+ stq $3, 4*8($30)
+ stq $4, 5*8($30)
+ stq $5, 6*8($30)
+ stq $6, 7*8($30)
+ stq $7, 8*8($30)
+ stq $16, 9*8($30)
+ stq $17, 10*8($30)
+ stq $18, 11*8($30)
+ stq $19, 12*8($30)
+ stq $20, 13*8($30)
+ stq $21, 14*8($30)
+ stq $22, 15*8($30)
+ stq $23, 16*8($30)
+ stq $25, 17*8($30)
+ stq $26, 18*8($30)
+ .frame $30, 20*8, $28
+ .prologue 1
+
+ mov $24, $16
+ jsr __down
+ mov $0, $24
+
+ ldq $28, 0*8($30)
+ ldq $0, 1*8($30)
+ ldq $1, 2*8($30)
+ ldq $2, 3*8($30)
+ ldq $3, 4*8($30)
+ ldq $4, 5*8($30)
+ ldq $5, 6*8($30)
+ ldq $6, 7*8($30)
+ ldq $7, 8*8($30)
+ ldq $16, 9*8($30)
+ ldq $17, 10*8($30)
+ ldq $18, 11*8($30)
+ ldq $19, 12*8($30)
+ ldq $20, 13*8($30)
+ ldq $21, 14*8($30)
+ ldq $22, 15*8($30)
+ ldq $23, 16*8($30)
+ ldq $25, 17*8($30)
+ ldq $26, 18*8($30)
+ lda $30, 20*8($30)
+ ret $31, ($28), 0
+ .end __down_failed_interruptible
+
+/* __up_wakeup takes the semaphore in $24, clobbers $24 and $28. */
+
+ .globl __up_wakeup
+ .ent __up_wakeup
+__up_wakeup:
+ ldgp $29,0($27)
+ lda $30, -20*8($30)
+ stq $28, 0*8($30)
+ stq $0, 1*8($30)
+ stq $1, 2*8($30)
+ stq $2, 3*8($30)
+ stq $3, 4*8($30)
+ stq $4, 5*8($30)
+ stq $5, 6*8($30)
+ stq $6, 7*8($30)
+ stq $7, 8*8($30)
+ stq $16, 9*8($30)
+ stq $17, 10*8($30)
+ stq $18, 11*8($30)
+ stq $19, 12*8($30)
+ stq $20, 13*8($30)
+ stq $21, 14*8($30)
+ stq $22, 15*8($30)
+ stq $23, 16*8($30)
+ stq $25, 17*8($30)
+ stq $26, 18*8($30)
+ .frame $30, 20*8, $28
+ .prologue 1
+
+ mov $24, $16
+ jsr __up
+
+ ldq $28, 0*8($30)
+ ldq $0, 1*8($30)
+ ldq $1, 2*8($30)
+ ldq $2, 3*8($30)
+ ldq $3, 4*8($30)
+ ldq $4, 5*8($30)
+ ldq $5, 6*8($30)
+ ldq $6, 7*8($30)
+ ldq $7, 8*8($30)
+ ldq $16, 9*8($30)
+ ldq $17, 10*8($30)
+ ldq $18, 11*8($30)
+ ldq $19, 12*8($30)
+ ldq $20, 13*8($30)
+ ldq $21, 14*8($30)
+ ldq $22, 15*8($30)
+ ldq $23, 16*8($30)
+ ldq $25, 17*8($30)
+ ldq $26, 18*8($30)
+ lda $30, 20*8($30)
+ ret $31, ($28), 0
+ .end __up_wakeup
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.2.0-pre7/linux/arch/arm/config.in Tue Dec 22 14:16:53 1998
+++ linux/arch/arm/config.in Thu Jan 14 10:29:28 1999
@@ -211,8 +211,6 @@
X
X source fs/Config.in
X
-source fs/nls/Config.in
-
X mainmenu_option next_comment
X comment 'Kernel hacking'
X
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.2.0-pre7/linux/arch/i386/config.in Fri Jan 8 22:36:00 1999
+++ linux/arch/i386/config.in Thu Jan 14 10:29:28 1999
@@ -159,8 +159,6 @@
X
X source fs/Config.in
X
-source fs/nls/Config.in
-
X if [ "$CONFIG_VT" = "y" ]; then
X mainmenu_option next_comment
X comment 'Console drivers'
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.2.0-pre7/linux/arch/i386/defconfig Thu Dec 31 10:28:58 1998
+++ linux/arch/i386/defconfig Sun Jan 17 22:57:39 1999
@@ -15,8 +15,12 @@
X # CONFIG_M586 is not set
X # CONFIG_M586TSC is not set
X CONFIG_M686=y
-CONFIG_TSC=y
-CONFIG_GOOD_APIC=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_TSC=y
+CONFIG_X86_GOOD_APIC=y
X # CONFIG_MATH_EMULATION is not set
X # CONFIG_MTRR is not set
X CONFIG_SMP=y
@@ -218,6 +222,7 @@
X # CONFIG_TR is not set
X # CONFIG_HOSTESS_SV11 is not set
X # CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
X # CONFIG_WAN_DRIVERS is not set
X # CONFIG_LAPBETHER is not set
X # CONFIG_X25_ASY is not set
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.2.0-pre7/linux/arch/i386/kernel/apm.c Fri Jan 8 22:36:00 1999
+++ linux/arch/i386/kernel/apm.c Thu Jan 14 22:57:25 1999
@@ -32,6 +32,7 @@
X * Sep 1998, Version 1.6
X * Nov 1998, Version 1.7
X * Jan 1999, Version 1.8
+ * Jan 1999, Version 1.9
X *
X * History:
X * 0.6b: first version in official kernel, Linux 1.3.46
@@ -78,6 +79,17 @@
X * change APM_NOINTS to CONFIG_APM_ALLOW_INTS
X * remove dependency on CONFIG_PROC_FS
X * Stephen Rothwell
+ * 1.9: Fix small typo. <la...@ilo.opole.pl>
+ * Try to cope with BIOS's that need to have all display
+ * devices blanked and not just the first one.
+ * Ross Paterson <ro...@soi.city.ac.uk>
+ * Fix segment limit setting it has always been wrong as
+ * the segments needed to have byte granularity.
+ * Mark a few things __init.
+ * Add hack to allow power off of SMP systems by popular request.
+ * Use CONFIG_SMP instead of __SMP__
+ * Ignore BOUNCES for three seconds.
+ * Stephen Rothwell
X *
X * APM 1.1 Reference:
X *
@@ -213,7 +225,7 @@
X #define APM_ZERO_SEGS
X
X /*
- * Define to make all set_limit calls use 64k limits. The APM 1.1 BIOS is
+ * Define to make all _set_limit calls use 64k limits. The APM 1.1 BIOS is
X * supposed to provide limit information that it recognizes. Many machines
X * do this correctly, but many others do not restrict themselves to their
X * claimed limit. When this happens, they will cause a segmentation
@@ -242,6 +254,12 @@
X #define APM_CHECK_TIMEOUT (HZ)
X
X /*
+ * If CONFIG_APM_IGNORE_SUSPEND_BOUNCE is defined then
+ * ignore suspend events for this amount of time
+ */
+#define BOUNCE_INTERVAL (3 * HZ)
+
+/*
X * Save a segment register away
X */
X #define savesegment(seg, where) \
@@ -276,6 +294,7 @@
X unsigned short segment;
X } apm_bios_entry;
X static int apm_enabled = 0;
+static int smp_hack = 0;
X #ifdef CONFIG_APM_CPU_IDLE
X static int clock_slowed = 0;
X #endif
@@ -300,7 +319,7 @@
X
X static struct timer_list apm_timer;
X
-static char driver_version[] = "1.8"; /* no spaces */
+static char driver_version[] = "1.9"; /* no spaces */
X
X #ifdef APM_DEBUG
X static char * apm_event_name[] = {
@@ -526,7 +545,15 @@
X
X void apm_power_off(void)
X {
- if (apm_enabled)
+ /*
+ * smp_hack == 2 means that we would have enabled APM support
+ * except there is more than one processor and so most of
+ * the APM stuff is unsafe. We will still try power down
+ * because is is useful to some people and they know what
+ * they are doing because they booted with the smp-power-off
+ * kernel option.
+ */
+ if (apm_enabled || (smp_hack == 2))
X (void) apm_set_power_state(APM_STATE_OFF);
X }
X
@@ -534,12 +561,19 @@
X /* Called by apm_display_blank and apm_display_unblank when apm_enabled. */
X static int apm_set_display_power_state(u_short state)
X {
- return set_power_state(0x0100, state);
+ int error;
+
+ /* Blank the first display device */
+ error = set_power_state(0x0100, state);
+ if (error == APM_BAD_DEVICE)
+ /* try to blank them all instead */
+ error = set_power_state(0x01ff, state);
+ return error;
X }
X #endif
X
X #ifdef CONFIG_APM_DO_ENABLE
-static int apm_enable_power_management(void)
+static int __init apm_enable_power_management(void)
X {
X u32 eax;
X
@@ -568,12 +602,9 @@
X return APM_SUCCESS;
X }
X
-#if 0
-/* not used anywhere */
-static int apm_get_battery_status(u_short which,
+static int apm_get_battery_status(u_short which, u_short *status,
X u_short *bat, u_short *life, u_short *nbat)
X {
- u_short status;
X u32 eax;
X u32 ebx;
X u32 ecx;
@@ -585,20 +616,20 @@
X if (which != 1)
X return APM_BAD_DEVICE;
X *nbat = 1;
- return apm_get_power_status(&status, bat, life);
+ return apm_get_power_status(status, bat, life);
X }
X
X if (apm_bios_call(0x530a, (0x8000 | (which)), 0, &eax,
X &ebx, &ecx, &edx, &esi))
X return (eax >> 8) & 0xff;
+ *status = ebx;
X *bat = ecx;
X *life = edx;
X *nbat = esi;
X return APM_SUCCESS;
X }
-#endif
X
-static int apm_engage_power_management(u_short device)
+static int __init apm_engage_power_management(u_short device)
X {
X u32 eax;
X
@@ -842,7 +873,8 @@
X "event 0x%02x\n", event);
X #endif
X #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
- if (ignore_bounce && ((jiffies - last_resume) > HZ))
+ if (ignore_bounce
+ && ((jiffies - last_resume) > BOUNCE_INTERVAL))
X ignore_bounce = 0;
X #endif
X switch (event) {
@@ -1152,6 +1184,7 @@
X unsigned short bx;
X unsigned short cx;
X unsigned short dx;
+ unsigned short nbat;
X unsigned short error;
X unsigned short ac_line_status = 0xff;
X unsigned short battery_status = 0xff;
@@ -1173,13 +1206,8 @@
X if (apm_bios_info.version > 0x100) {
X battery_flag = (cx >> 8) & 0xff;
X if (dx != 0xffff) {
- if ((dx & 0x8000) == 0x8000) {
- units = "min";
- time_units = dx & 0x7ffe;
- } else {
- units = "sec";
- time_units = dx & 0x7fff;
- }
+ units = (dx & 0x8000) ? "min" : "sec";
+ time_units = dx & 0x7fff;
X }
X }
X }
@@ -1249,6 +1277,8 @@
X str += 3;
X if (strncmp(str, "debug", 5) == 0)
X debug = !invert;
+ if (strncmp(str, "smp-power-off", 13) == 0)
+ smp_hack = !invert;
X str = strchr(str, ',');
X if (str != NULL)
X str += strspn(str, ", \t");
@@ -1289,17 +1319,18 @@
X
X /* BIOS < 1.2 doesn't set cseg_16_len */
X if (apm_bios_info.version < 0x102)
- apm_bios_info.cseg_16_len = 0xFFFF; /* 64k */
+ apm_bios_info.cseg_16_len = 0; /* 64k */
X
X if (debug) {
X printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x",
X apm_bios_info.cseg, apm_bios_info.offset,
X apm_bios_info.cseg_16, apm_bios_info.dseg);
X if (apm_bios_info.version > 0x100)
- printk(" cseg len %x, cseg16 len %x, dseg len %x",
+ printk(" cseg len %x, dseg len %x",
X apm_bios_info.cseg_len,
- apm_bios_info.cseg_16_len,
X apm_bios_info.dseg_len);
+ if (apm_bios_info.version > 0x101)
+ printk(" cseg16 len %x", apm_bios_info.cseg_16_len);
X printk("\n");
X }
X
@@ -1307,12 +1338,6 @@
X printk(KERN_NOTICE "apm: disabled on user request.\n");
X return;
X }
-#ifdef __SMP__
- if (smp_num_cpus > 1) {
- printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
- return;
- }
-#endif
X
X /*
X * Set up a segment that references the real mode segment 0x40
@@ -1322,7 +1347,7 @@
X */
X set_base(gdt[APM_40 >> 3],
X __va((unsigned long)0x40 << 4));
- set_limit(gdt[APM_40 >> 3], 4096 - (0x40 << 4));
+ _set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4));
X
X apm_bios_entry.offset = apm_bios_info.offset;
X apm_bios_entry.segment = APM_CS;
@@ -1332,23 +1357,36 @@
X __va((unsigned long)apm_bios_info.cseg_16 << 4));
X set_base(gdt[APM_DS >> 3],
X __va((unsigned long)apm_bios_info.dseg << 4));
- if (apm_bios_info.version == 0x100) {
- set_limit(gdt[APM_CS >> 3], 64 * 1024);
- set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
- set_limit(gdt[APM_DS >> 3], 64 * 1024);
- } else {
-#ifdef APM_RELAX_SEGMENTS
+#ifndef APM_RELAX_SEGMENTS
+ if (apm_bios_info.version == 0x100)
+#endif
+ {
X /* For ASUS motherboard, Award BIOS rev 110 (and others?) */
- set_limit(gdt[APM_CS >> 3], 64 * 1024);
+ _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
X /* For some unknown machine. */
- set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
+ _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
X /* For the DEC Hinote Ultra CT475 (and others?) */
- set_limit(gdt[APM_DS >> 3], 64 * 1024);
-#else
- set_limit(gdt[APM_CS >> 3], apm_bios_info.cseg_len);
- set_limit(gdt[APM_CS_16 >> 3], apm_bios_info.cseg_16_len);
- set_limit(gdt[APM_DS >> 3], apm_bios_info.dseg_len);
+ _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
+ }
+#ifndef APM_RELAX_SEGMENTS
+ else {
+ _set_limit((char *)&gdt[APM_CS >> 3],
+ (apm_bios_info.cseg_len - 1) & 0xffff);
+ _set_limit((char *)&gdt[APM_CS_16 >> 3],
+ (apm_bios_info.cseg_16_len - 1) & 0xffff);
+ _set_limit((char *)&gdt[APM_DS >> 3],
+ (apm_bios_info.dseg_len - 1) & 0xffff);
+ }
+#endif
+#ifdef CONFIG_SMP
+ if (smp_num_cpus > 1) {
+ printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+ if (smp_hack)
+ smp_hack = 2;
+ return;
+ }
X #endif
+ if (apm_bios_info.version > 0x100) {
X /*
X * We only support BIOSs up to version 1.2
X */
@@ -1360,7 +1398,7 @@
X }
X }
X if (debug) {
- printk(KERN_INFO "apm: onnection version %d.%d\n",
+ printk(KERN_INFO "apm: Connection version %d.%d\n",
X (apm_bios_info.version >> 8) & 0xff,
X apm_bios_info.version & 0xff );
X
@@ -1381,23 +1419,23 @@
X case 3: bat_stat = "charging"; break;
X default: bat_stat = "unknown"; break;
X }
- printk(KERN_INFO "apm: AC %s, battery status %s, battery life ",
+ printk(KERN_INFO
+ "apm: AC %s, battery status %s, battery life ",
X power_stat, bat_stat);
X if ((cx & 0xff) == 0xff)
X printk("unknown\n");
X else
X printk("%d%%\n", cx & 0xff);
X if (apm_bios_info.version > 0x100) {
- printk("apm: battery flag 0x%02x, battery life ",
+ printk(KERN_INFO
+ "apm: battery flag 0x%02x, battery life ",
X (cx >> 8) & 0xff);
X if (dx == 0xffff)
X printk("unknown\n");
- else {
- if ((dx & 0x8000))
- printk("%d minutes\n", dx & 0x7ffe );
- else
- printk("%d seconds\n", dx & 0x7fff );
- }
+ else
+ printk("%d %s\n", dx & 0x7fff,
+ (dx & 0x8000) ?
+ "minutes" : "seconds");
X }
X }
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.2.0-pre7/linux/arch/i386/kernel/entry.S Fri Jan 8 22:36:00 1999
+++ linux/arch/i386/kernel/entry.S Mon Jan 18 09:55:50 1999
@@ -559,7 +559,7 @@
X .long SYMBOL_NAME(sys_sendfile)
X .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
X .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
- .long SYMBOL_NAME(sys_vfork) /* 190 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* 190 */
X
X /*
X * NOTE!! This doesn't have to be exact - we just have
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.2.0-pre7/linux/arch/i386/kernel/head.S Wed Sep 9 14:51:05 1998
+++ linux/arch/i386/kernel/head.S Thu Jan 14 22:57:25 1999
@@ -534,10 +534,14 @@
X .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */
X .quad 0x0000000000000000 /* not used */
X .quad 0x0000000000000000 /* not used */
- .quad 0x00c0920000000000 /* 0x40 APM set up for bad BIOS's */
- .quad 0x00c09a0000000000 /* 0x48 APM CS code */
- .quad 0x00809a0000000000 /* 0x50 APM CS 16 code (16 bit) */
- .quad 0x00c0920000000000 /* 0x58 APM DS data */
+ /*
+ * The APM segments have byte granularity and their bases
+ * and limits are set at run time.
+ */
+ .quad 0x0040920000000000 /* 0x40 APM set up for bad BIOS's */
+ .quad 0x00409a0000000000 /* 0x48 APM CS code */
+ .quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */
+ .quad 0x0040920000000000 /* 0x58 APM DS data */
X .fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */
X
X /*
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.2.0-pre7/linux/arch/i386/kernel/process.c Wed Jan 13 15:00:41 1999
+++ linux/arch/i386/kernel/process.c Mon Jan 18 09:55:50 1999
@@ -475,24 +475,27 @@
X
X void release_segments(struct mm_struct *mm)
X {
- /* forget local segments */
- __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs"
- : /* no outputs */
- : "r" (0));
X if (mm->segments) {
X void * ldt = mm->segments;
-
- /*
- * Get the LDT entry from init_task.
- */
- current->tss.ldt = _LDT(0);
- load_ldt(0);
-
X mm->segments = NULL;
X vfree(ldt);
X }
X }
X
+void forget_segments(void)
+{
+ /* forget local segments */
+ __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs"
+ : /* no outputs */
+ : "r" (0));
+
+ /*
+ * Get the LDT entry from init_task.
+ */
+ current->tss.ldt = _LDT(0);
+ load_ldt(0);
+}
+
X /*
X * Create a kernel thread
X */
@@ -778,21 +781,7 @@
X newsp = regs.ecx;
X if (!newsp)
X newsp = regs.esp;
- return do_fork(clone_flags & ~CLONE_VFORK, newsp, &regs);
-}
-
-asmlinkage int sys_vfork(struct pt_regs regs)
-{
- int child;
- struct semaphore sem = MUTEX_LOCKED;
-
- current->vfork_sem = &sem;
- child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs);
-
- if (child > 0)
- down(&sem);
-
- return child;
+ return do_fork(clone_flags, newsp, &regs);
X }
X
X /*
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/i386/lib/checksum.S linux/arch/i386/lib/checksum.S
--- v2.2.0-pre7/linux/arch/i386/lib/checksum.S Mon Dec 28 15:00:52 1998
+++ linux/arch/i386/lib/checksum.S Fri Jan 15 14:36:20 1999
@@ -299,8 +299,8 @@
X adcl %edx, %eax
X DST( movl %edx, 28(%edi) )
X
-SRC( lea 32(%esi), %esi )
-DST( lea 32(%edi), %edi )
+ lea 32(%esi), %esi
+ lea 32(%edi), %edi
X dec %ecx
X jne 1b
X adcl $0, %eax
@@ -312,8 +312,8 @@
X SRC(3: movl (%esi), %ebx )
X adcl %ebx, %eax
X DST( movl %ebx, (%edi) )
-SRC( lea 4(%esi), %esi )
-DST( lea 4(%edi), %edi )
+ lea 4(%esi), %esi
+ lea 4(%edi), %edi
X dec %edx
X jne 3b
X adcl $0, %eax
@@ -322,9 +322,9 @@
X cmpl $2, %ecx
X jb 5f
X SRC( movw (%esi), %cx )
-SRC( leal 2(%esi), %esi )
+ leal 2(%esi), %esi
X DST( movw %cx, (%edi) )
-DST( leal 2(%edi), %edi )
+ leal 2(%edi), %edi
X je 6f
X shll $16,%ecx
X SRC(5: movb (%esi), %cl )
@@ -337,8 +337,8 @@
X # Exception handler:
X .section .fixup, "ax"
X
-6000:
-
+6001:
+ movl ARGBASE+20(%esp), %ebx # src_err_ptr
X movl $-EFAULT, (%ebx)
X
X # zero the complete destination - computing the rest
@@ -350,13 +350,10 @@
X
X jmp 5000b
X
-6001:
- movl ARGBASE+20(%esp), %ebx # src_err_ptr
- jmp 6000b
-
X 6002:
X movl ARGBASE+24(%esp), %ebx # dst_err_ptr
- jmp 6000b
+ movl $-EFAULT,(%ebx)
+ jmp 5000b
X
X .previous
X
@@ -426,17 +423,17 @@
X adcl $0, %eax
X 7:
X .section .fixup, "ax"
-6000: movl $-EFAULT, (%ebx)
+6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
+ movl $-EFAULT, (%ebx)
X # zero the complete destination (computing the rest is too much work)
X movl ARGBASE+8(%esp),%edi # dst
X movl ARGBASE+12(%esp),%ecx # len
X xorl %eax,%eax
X rep; stosb
X jmp 7b
-6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
- jmp 6000b
X 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr
- jmp 6000b
+ movl $-EFAULT, (%ebx)
+ jmp 7b
X .previous
X
X popl %esi
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.2.0-pre7/linux/arch/m68k/config.in Thu Jan 7 15:11:36 1999
+++ linux/arch/m68k/config.in Thu Jan 14 10:29:28 1999
@@ -356,8 +356,6 @@
X endmenu
X fi
X
-source fs/nls/Config.in
-
X mainmenu_option next_comment
X comment 'Kernel hacking'
X
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.2.0-pre7/linux/arch/mips/config.in Fri Oct 23 22:01:19 1998
+++ linux/arch/mips/config.in Thu Jan 14 10:29:28 1999
@@ -192,8 +192,6 @@
X
X source fs/Config.in
X
-source fs/nls/Config.in
-
X comment 'Console drivers'
X source drivers/video/Config.in
X
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.2.0-pre7/linux/arch/ppc/config.in Mon Dec 28 15:00:52 1998
+++ linux/arch/ppc/config.in Thu Jan 14 10:29:28 1999
@@ -167,7 +167,6 @@
X
X source drivers/char/Config.in
X source fs/Config.in
-source fs/nls/Config.in
X
X mainmenu_option next_comment
X comment 'Sound'
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.2.0-pre7/linux/arch/sparc/config.in Tue Dec 22 14:16:54 1998
+++ linux/arch/sparc/config.in Thu Jan 14 10:29:28 1999
@@ -176,8 +176,6 @@
X
X source fs/Config.in
X
-source fs/nls/Config.in
-
X mainmenu_option next_comment
X comment 'Watchdog'
X
diff -u --recursive --new-file v2.2.0-pre7/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.2.0-pre7/linux/arch/sparc64/config.in Tue Dec 22 14:16:54 1998
+++ linux/arch/sparc64/config.in Thu Jan 14 10:29:28 1999
@@ -239,8 +239,6 @@
X
X source fs/Config.in
X
-source fs/nls/Config.in
-
X mainmenu_option next_comment
X comment 'Watchdog'
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.2.0-pre7/linux/drivers/block/hd.c Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/hd.c Thu Jan 14 10:31:41 1999
@@ -783,6 +783,7 @@
X hd_ioctl, /* ioctl */
X NULL, /* mmap */
X hd_open, /* open */
+ NULL, /* flush */
X hd_release, /* release */
X block_fsync /* fsync */
X };
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.2.0-pre7/linux/drivers/block/ide-cd.c Mon Dec 28 15:00:52 1998
+++ linux/drivers/block/ide-cd.c Mon Jan 18 12:47:33 1999
@@ -2,7 +2,7 @@
X * linux/drivers/block/ide-cd.c
X * Copyright (C) 1994, 1995, 1996 scott snyder <sny...@fnald0.fnal.gov>
X * Copyright (C) 1996-1998 Erik Andersen <ande...@debian.org>
- * Copyright (C) 1998 Jens Axboe and Chris Zwilling
+ * Copyright (C) 1998, 1999 Jens Axboe
X *
X * May be copied or modified under the terms of the GNU General Public
X * License. See linux/COPYING for more information.
@@ -17,7 +17,7 @@
X * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
X *
X * Drives that deviate from the ATAPI standard will be accomodated as much
- * as possable via compile time or command-line options. Since I only have
+ * as possible via compile time or command-line options. Since I only have
X * a few drives, you generally need to send me patches...
X *
X * ----------------------------------
@@ -31,9 +31,8 @@
X * use them (like trying to close the tray in drives that can't).
X * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
X * boot
- * -Handle older drives that can't report their speed. (i.e. check if they
- * support a version of ATAPI where they can report their speed before
- * checking their speed and believing what they return).
+ * -Integrate DVD-ROM support in driver. Thanks to Merete Gotsæd-Petersen
+ * of Pioneer Denmark for providing me with a drive for testing.
X *
X *
X * ----------------------------------
@@ -2574,8 +2573,7 @@
X curslot = CDROM_STATE_FLAGS (drive)->sanyo_slot;
X if (curslot == 3)
X curslot = 0;
- }
- else
+ } else
X #endif /* not STANDARD_ATAPI */
X {
X stat = cdrom_read_changer_info (drive);
@@ -2656,10 +2654,10 @@
X return CDS_DISC_OK;
X
X if (my_reqbuf.sense_key == NOT_READY) {
- /* With my NEC260, at least, we can't distinguish
- between tray open and tray closed but no disc
- inserted. */
- return CDS_TRAY_OPEN;
+ /* ATAPI doesn't have anything that can help
+ us decide whether the drive is really
+ emtpy or the tray is just open. irk. */
+ return CDS_TRAY_OPEN;
X }
X
X return CDS_DRIVE_NOT_READY;
@@ -2835,13 +2833,11 @@
X static
X int ide_cdrom_probe_capabilities (ide_drive_t *drive)
X {
- int stat, nslots, attempts = 3;
+ int stat, nslots = 0, attempts = 3;
X struct {
X char pad[8];
X struct atapi_capabilities_page cap;
X } buf;
-
- nslots = 0;
X
X if (CDROM_CONFIG_FLAGS (drive)->nec260)
X return nslots;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/ide-cd.h linux/drivers/block/ide-cd.h
--- v2.2.0-pre7/linux/drivers/block/ide-cd.h Mon Dec 28 15:00:52 1998
+++ linux/drivers/block/ide-cd.h Mon Jan 18 17:33:48 1999
@@ -4,7 +4,7 @@
X * linux/drivers/block/ide_modes.h
X *
X * Copyright (C) 1996 Erik Andersen
- * Copyright (C) 1998 Jens Axboe and Chris Zwilling
+ * Copyright (C) 1998, 1999 Jens Axboe
X */
X
X #include <asm/byteorder.h>
@@ -298,7 +298,7 @@
X /* Drive supports reading CD-R discs with addressing method 2 */
X __u8 method2 : 1; /* reserved in 1.2 */
X /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_read : 1; /* reserved in 1.2 */
+ __u8 cd_rw_read : 1; /* reserved in 1.2 */
X /* Drive supports read from CD-R discs (orange book, part II) */
X __u8 cd_r_read : 1; /* reserved in 1.2 */
X #elif defined(__LITTLE_ENDIAN_BITFIELD)
@@ -307,8 +307,7 @@
X /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
X __u8 cd_rw_read : 1; /* reserved in 1.2 */
X /* Drive supports reading CD-R discs with addressing method 2 */
- __u8 method2 : 1; /* reserved in 1.2 */
- __u8 reserved2 : 5;
+ __u8 reserved2 : 5;
X #else
X #error "Please fix <asm/byteorder.h>"
X #endif
@@ -316,7 +315,7 @@
X #if defined(__BIG_ENDIAN_BITFIELD)
X __u8 reserved3 : 6;
X /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_write : 1; /* reserved in 1.2 */
+ __u8 cd_rw_write : 1; /* reserved in 1.2 */
X /* Drive supports write to CD-R discs (orange book, part II) */
X __u8 cd_r_write : 1; /* reserved in 1.2 */
X #elif defined(__LITTLE_ENDIAN_BITFIELD)
@@ -324,14 +323,14 @@
X /* Drive can write to CD-R discs (orange book, part II) */
X __u8 cd_r_write : 1; /* reserved in 1.2 */
X /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_write : 1; /* reserved in 1.2 */
+ __u8 cd_rw_write : 1; /* reserved in 1.2 */
X __u8 reserved3 : 6;
X #else
X #error "Please fix <asm/byteorder.h>"
X #endif
X
X #if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved4 : 1;
+ __u8 reserved4 : 4;
X /* Drive can read multisession discs. */
X __u8 multisession : 1;
X /* Drive can read mode 2, form 2 data. */
@@ -404,7 +403,7 @@
X
X #if defined(__BIG_ENDIAN_BITFIELD)
X /* Drive mechanism types. */
- mechtype_t mechtype : 3;
+ mechtype_t mechtype : 3;
X __u8 reserved6 : 1;
X /* Drive can eject a disc or changer cartridge. */
X __u8 eject : 1;
@@ -426,7 +425,7 @@
X __u8 eject : 1;
X __u8 reserved6 : 1;
X /* Drive mechanism types. */
- mechtype_t mechtype : 3;
+ mechtype_t mechtype : 3;
X #else
X #error "Please fix <asm/byteorder.h>"
X #endif
@@ -745,7 +744,7 @@
X
X { 0x6300, "End of user area encountered on this track" },
X
- { 0x6400, "Illegal mode for this track" },
+ { 0x6400, "Illegal mode for this track or incompatible medium" },
X
X { 0xb900, "Play operation oborted (sic)" },
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
--- v2.2.0-pre7/linux/drivers/block/ide-disk.c Thu Jan 7 15:11:36 1999
+++ linux/drivers/block/ide-disk.c Thu Jan 14 22:58:47 1999
@@ -742,8 +742,8 @@
X * if possible, give fdisk access to more of the drive,
X * by correcting bios_cyls:
X */
- if ((capacity >= (id->cyls * id->heads * id->sectors)) &&
- (!drive->forced_geom)) {
+ if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) &&
+ (!drive->forced_geom) && drive->bios_sect && drive->bios_head) {
X drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
X #ifdef DEBUG
X printk("Fixing Geometry :: CHS=%d/%d/%d to CHS=%d/%d/%d\n",
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- v2.2.0-pre7/linux/drivers/block/ide-dma.c Fri Jan 8 22:36:04 1999
+++ linux/drivers/block/ide-dma.c Sun Jan 17 18:23:01 1999
@@ -369,7 +369,11 @@
X return 1;
X }
X
-__initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports))
+/*
+ * This can be called for a dynamically installed interface. Don't initfunc it
+ */
+
+void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
X {
X static unsigned long dmatable = 0;
X static unsigned leftover = 0;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- v2.2.0-pre7/linux/drivers/block/ide-pci.c Fri Oct 23 22:01:20 1998
+++ linux/drivers/block/ide-pci.c Thu Jan 14 22:53:02 1999
@@ -44,6 +44,7 @@
X #define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565})
X #define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF})
X #define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
+#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A})
X #define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF})
X #define DEVID_HPT343 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343})
X
@@ -137,6 +138,7 @@
X {DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
X {DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
X {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 },
+ {DEVID_UM8886A, "UM8886A", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
X {DEVID_UM8886BF,"UM8886BF", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
X {DEVID_HPT343, "HPT343", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 },
X {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }};
@@ -386,6 +388,10 @@
X mate->serialized = 1;
X }
X }
+ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF))
+ hwif->irq = hwif->channel ? 15 : 14;
+
X #ifdef CONFIG_BLK_DEV_IDEDMA
X if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513))
X autodma = 0;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.2.0-pre7/linux/drivers/block/ide.c Thu Jan 7 15:11:36 1999
+++ linux/drivers/block/ide.c Fri Jan 15 14:36:20 1999
@@ -2132,6 +2132,12 @@
X return -EIO;
X return 0;
X }
+ case HDIO_UNREGISTER_HWIF:
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ /* should I check here for arg > MAX_HWIFS, or
+ just let ide_unregister fail silently? -- shaver */
+ ide_unregister(arg);
+ return 0;
X case HDIO_SET_NICE:
X if (!capable(CAP_SYS_ADMIN)) return -EACCES;
X if (drive->driver == NULL)
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.2.0-pre7/linux/drivers/block/loop.c Fri Nov 27 13:09:23 1998
+++ linux/drivers/block/loop.c Thu Jan 14 10:33:36 1999
@@ -225,6 +225,7 @@
X if (!create_missing_block(lo, block, blksize)) {
X goto error_out_lock;
X }
+ real_block = bmap(lo->lo_dentry->d_inode, block);
X }
X
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.2.0-pre7/linux/drivers/block/ps2esdi.c Thu Nov 12 16:21:18 1998
+++ linux/drivers/block/ps2esdi.c Thu Jan 14 10:31:41 1999
@@ -44,6 +44,7 @@
X #include <linux/blk.h>
X #include <linux/mca.h>
X #include <linux/init.h>
+#include <linux/ioport.h>
X
X #include <asm/system.h>
X #include <asm/io.h>
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.2.0-pre7/linux/drivers/cdrom/cdrom.c Fri Jan 8 22:36:04 1999
+++ linux/drivers/cdrom/cdrom.c Mon Jan 18 17:33:01 1999
@@ -1,7 +1,7 @@
X /* linux/drivers/cdrom/cdrom.c.
X Copyright (c) 1996, 1997 David A. van Leeuwen.
X Copyright (c) 1997, 1998 Erik Andersen <ande...@debian.org>
- Copyright (c) 1998 Jens Axboe and Chris Zwilling
+ Copyright (c) 1998, 1999 Jens Axboe
X
X May be copied or modified under the terms of the GNU General Public
X License. See linux/COPYING for more information.
@@ -96,11 +96,18 @@
X -- Check if drive is capable of doing what we ask before blindly changing
X cdi->options in various ioctl.
X -- Added version to proc entry.
+
+ 2.52 Jan 16, 1998 - Jens Axboe <ax...@image.dk>
+ -- Fixed an error in open_for_data where we would sometimes not return
+ the correct error value. Thanks Huba Gaspar <hu...@softcell.hu>.
+ -- Fixed module usage count - usage was based on /proc/sys/dev
+ instead of /proc/sys/dev/cdrom. This could lead to an oops when other
+ modules had entries in dev.
X
X -------------------------------------------------------------------------*/
X
-#define REVISION "Revision: 2.51"
-#define VERSION "Id: cdrom.c 2.51 1998/12/20"
+#define REVISION "Revision: 2.52"
+#define VERSION "Id: cdrom.c 2.52 1999/01/16"
X
X /* I use an error-log mask to give fine grain control over the type of
X messages dumped to the system logs. The available masks include: */
@@ -363,7 +370,7 @@
X goto clean_up_and_return;
X }
X } else {
- cdinfo(CD_OPEN, "bummer. this driver can't close the tray.\n");
+ cdinfo(CD_OPEN, "bummer. this drive can't close the tray.\n");
X ret=-ENOMEDIUM;
X goto clean_up_and_return;
X }
@@ -371,6 +378,7 @@
X ret = cdo->drive_status(cdi, CDSL_CURRENT);
X if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
X cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n");
+ cdinfo(CD_OPEN, "tray might not contain a medium.\n");
X ret=-ENOMEDIUM;
X goto clean_up_and_return;
X }
@@ -997,8 +1005,13 @@
X int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
X void *buffer, size_t *lenp)
X {
- int retv,pos;
+ int pos;
X struct cdrom_device_info *cdi;
+
+ if (!*lenp || (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
X
X pos = sprintf(cdrom_drive_info, "CD-ROM information, " VERSION "\n");
X
@@ -1061,18 +1074,14 @@
X
X strcpy(cdrom_drive_info+pos,"\n\n");
X *lenp=pos+3;
- if (!write) {
- retv = proc_dostring(ctl, write, filp, buffer, lenp);
- }
- else
- retv = proc_dostring(ctl, write, filp, buffer, lenp);
- return retv;
+
+ return proc_dostring(ctl, write, filp, buffer, lenp);
X }
X
X /* Place files in /proc/sys/dev/cdrom */
X ctl_table cdrom_table[] = {
X {DEV_CDROM_INFO, "info", &cdrom_drive_info,
- CDROM_STR_SIZE*sizeof(char), 0444, NULL, &cdrom_sysctl_info},
+ CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info},
X {0}
X };
X
@@ -1099,20 +1108,23 @@
X */
X static void cdrom_procfs_modcount(struct inode *inode, int fill)
X {
- if (fill)
- MOD_INC_USE_COUNT;
- else
- MOD_DEC_USE_COUNT;
+ if (fill) {
+ MOD_INC_USE_COUNT;
+ } else {
+ MOD_DEC_USE_COUNT;
+ }
X }
X
X static void cdrom_sysctl_register(void)
X {
X static int initialized = 0;
X
- if ( initialized == 1 )
+ if (initialized == 1)
X return;
- cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 0);
+
+ cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
X cdrom_root_table->de->fill_inode = &cdrom_procfs_modcount;
+
X initialized = 1;
X }
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.2.0-pre7/linux/drivers/char/bttv.c Tue Dec 22 14:16:55 1998
+++ linux/drivers/char/bttv.c Sun Jan 17 18:28:06 1999
@@ -17,66 +17,87 @@
X You should have received a copy of the GNU General Public License
X along with this program; if not, write to the Free Software
X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Modified to put the RISC code writer in the kernel and to fit a
- common (and I hope safe) kernel interface. When we have an X extension
- all will now be really sweet.
-
- TODO:
-
- * move norm from tuner to channel struct!?
- composite source from a satellite tuner can deliver different norms
- depending on tuned channel
- * mmap VBI data?
- * fix RAW Composite grabbing for NTSC
- * fix VBI reading double frames when grabbing is active
- * allow for different VDELAYs
- * handle tda8425 properly
X */
X
X #include <linux/module.h>
+#include <linux/version.h>
X #include <linux/delay.h>
X #include <linux/errno.h>
X #include <linux/fs.h>
X #include <linux/kernel.h>
X #include <linux/major.h>
X #include <linux/malloc.h>
-#include <linux/vmalloc.h>
X #include <linux/mm.h>
+#if LINUX_VERSION_CODE >= 0x020100
+#include <linux/poll.h>
+#endif
X #include <linux/pci.h>
X #include <linux/signal.h>
X #include <asm/io.h>
+#include <linux/ioport.h>
X #include <asm/pgtable.h>
X #include <asm/page.h>
X #include <linux/sched.h>
X #include <asm/segment.h>
X #include <linux/types.h>
X #include <linux/wrapper.h>
-
-#include <linux/videodev.h>
+#include <linux/interrupt.h>
X #include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= 0x020100
X #include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+#else
+#include <linux/bios32.h>
+#define mdelay(x) udelay((x)*1000)
+#define signal_pending(current) (current->signal & ~current->blocked)
+#define sigfillset(set)
+
+static inline int time_before(unsigned long a, unsigned long b)
+{
+ return((long)((a) - (b)) < 0L);
+}
X
+static inline unsigned long
+copy_to_user(void *to, const void *from, unsigned long n)
+{
+ memcpy_tofs(to,from,n);
+ return 0;
+}
+
+static inline unsigned long
+copy_from_user(void *to, const void *from, unsigned long n)
+{
+ memcpy_fromfs(to,from,n);
+ return 0;
+}
+#define ioremap vremap
+#define iounmap vfree
+#endif
+
+#include <linux/videodev.h>
X #include <linux/i2c.h>
X #include "bttv.h"
X #include "tuner.h"
X
-#define DEBUG(x) /* Debug driver */
+#define DEBUG(x) /* Debug driver */
X #define IDEBUG(x) /* Debug interrupt handler */
X
+#if LINUX_VERSION_CODE >= 0x020117
X MODULE_PARM(vidmem,"i");
X MODULE_PARM(triton1,"i");
X MODULE_PARM(remap,"1-4i");
X MODULE_PARM(radio,"1-4i");
X MODULE_PARM(card,"1-4i");
X MODULE_PARM(pll,"1-4i");
-
-static int find_vga(void);
-static void bt848_set_risc_jmps(struct bttv *btv);
+#endif
X
X /* Anybody who uses more than four? */
X #define BTTV_MAX 4
X
+static int find_vga(void);
+static void bt848_set_risc_jmps(struct bttv *btv);
+
X static unsigned int vidmem=0; /* manually set video mem address */
X static int triton1=0;
X #ifndef USE_PLL
@@ -98,15 +119,16 @@
X static struct bttv bttvs[BTTV_MAX];
X
X #define I2C_TIMING (0x7<<4)
-#define I2C_DELAY 50 /* Was 10 - some reports that more is needed
- regardless of what the spec says */
+#define I2C_DELAY 10
X #define I2C_SET(CTRL,DATA) \
X { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
X #define I2C_GET() (btread(BT848_I2C)&1)
X
-#define EEPROM_WRITE_DELAY 20000
+#define EEPROM_WRITE_DELAY 20000
X #define BURSTOFFSET 76
X
+
+
X /*******************************/
X /* Memory management functions */
X /*******************************/
@@ -191,6 +213,8 @@
X }
X }
X
+
+
X /*
X * Create the giant waste of buffer space we need for now
X * until we get DMA to user space sorted out (probably 2.3.x)
@@ -388,7 +412,9 @@
X I2C_BUSID_BT848,
X NULL,
X
+#if LINUX_VERSION_CODE >= 0x020100
X SPIN_LOCK_UNLOCKED,
+#endif
X
X attach_inform,
X detach_inform,
@@ -400,6 +426,70 @@
X };
X
X /* ----------------------------------------------------------------------- */
+/* some hauppauge specific stuff */
+
+static unsigned char eeprom_data[256];
+static struct HAUPPAUGE_TUNER
+{
+ int id;
+ char *name;
+}
+hauppauge_tuner[] =
+{
+ { TUNER_ABSENT, "" },
+ { TUNER_ABSENT, "External" },
+ { TUNER_ABSENT, "Unspecified" },
+ { TUNER_ABSENT, "Philips FI1216" },
+ { TUNER_ABSENT, "Philips FI1216MF" },
+ { TUNER_PHILIPS_NTSC, "Philips FI1236" },
+ { TUNER_ABSENT, "Philips FI1246" },
+ { TUNER_ABSENT, "Philips FI1256" },
+ { TUNER_PHILIPS_PAL, "Philips FI1216 MK2" },
+ { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
+ { TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" },
+ { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
+ { TUNER_ABSENT, "Philips FI1256 MK2" },
+ { TUNER_ABSENT, "Temic 4032FY5" },
+ { TUNER_TEMIC_PAL, "Temic 4002FH5" },
+ { TUNER_TEMIC_PAL_I, "Temic 4062FY5" },
+ { TUNER_ABSENT, "Philips FR1216 MK2" },
+ { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
+ { TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" },
+ { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
+ { TUNER_ABSENT, "Philips FR1256 MK2" },
+ { TUNER_PHILIPS_PAL, "Philips FM1216" },
+ { TUNER_ABSENT, "Philips FM1216MF" },
+ { TUNER_PHILIPS_NTSC, "Philips FM1236" },
+};
+
+static void
+hauppauge_eeprom(struct i2c_bus *bus)
+{
+ struct bttv *btv = (struct bttv*)bus->data;
+
+ readee(bus, eeprom_data);
+ if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER))
+ {
+ btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id;
+ printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr,
+ hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type);
+ }
+}
+
+static void
+hauppauge_msp_reset(struct bttv *btv)
+{
+ /* Reset the MSP on some Hauppauge cards */
+ /* Thanks to Kyösti Mälkki (kma...@cc.hut.fi)! */
+ /* Can this hurt cards without one? What about Miros with MSP? */
+ btaor(32, ~32, BT848_GPIO_OUT_EN);
+ btaor(0, ~32, BT848_GPIO_DATA);
+ udelay(2500);
+ btaor(32, ~32, BT848_GPIO_DATA);
+ /* btaor(0, ~32, BT848_GPIO_OUT_EN); */
+}
+
+/* ----------------------------------------------------------------------- */
X
X
X struct tvcard
@@ -437,25 +527,17 @@
X {0, 0xc00, 0x800, 0x400, 0xc00, 0}},
X /* TurboTV */
X { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
- /* Newer Hauppauge (bt878) */
+ /* Newer Hauppauge (bt878) */
X { 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}},
- /* MIRO PCTV pro */


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 03'
echo 'File patch-2.2.0-pre8 is continued in part 04'
echo 04 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part04

#!/bin/sh
# this is part 04 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 04; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

- { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
+ /* MIRO PCTV pro */
+ { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
X /* ADS Technologies Channel Surfer TV (and maybe TV+FM) */
- {
- 3, 4, 0, 2, 0x0F,
- { 0x02, 0x03, 0x01, 0x01},
- { 0x0D, 0x0E, 0x0B, 0x07, 0x00, 0x00},
- 0x00
- },
+ { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
+ /* AVerMedia TVCapture 98 */
+ { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
X };
X #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
X
-
-/*
- * Tuner, Radio, internal, external and mute
- */
-
X static void audio(struct bttv *btv, int mode)
X {
X btaor(tvcards[btv->type].gpiomask, ~tvcards[btv->type].gpiomask,
@@ -543,16 +625,16 @@
X fout*=12;
X fi=fout/fin;
X
- fout=(fout-fin*fi)*256;
+ fout=(fout%fin)*256;
X fh=fout/fin;
X
- fout=(fout-fin*fh)*256;
+ fout=(fout%fin)*256;
X fl=fout/fin;
X
X /*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/
- btwrite(fl,BT848_PLL_F_LO);
- btwrite(fh,BT848_PLL_F_HI);
- btwrite(fi|BT848_PLL_X,BT848_PLL_XCI);
+ btwrite(fl, BT848_PLL_F_LO);
+ btwrite(fh, BT848_PLL_F_HI);
+ btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
X }
X
X static int set_pll(struct bttv *btv)
@@ -594,7 +676,7 @@
X }
X while(time_before(jiffies,tv));
X
- for (i=0; i<100; i++)
+ for (i=0; i<10; i++)
X {
X if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK))
X btwrite(0,BT848_DSTATUS);
@@ -615,13 +697,14 @@
X static void bt848_muxsel(struct bttv *btv, unsigned int input)
X {
X btaor(tvcards[btv->type].gpiomask2,~tvcards[btv->type].gpiomask2,
- BT848_GPIO_OUT_EN);
+ BT848_GPIO_OUT_EN);
X
X /* This seems to get rid of some synchronization problems */
X btand(~(3<<5), BT848_IFORM);
X mdelay(10);
-
- input %= tvcards[btv->type].video_inputs;
+
+
+ input %= tvcards[btv->type].video_inputs;
X if (input==tvcards[btv->type].svhs)
X {
X btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
@@ -639,13 +722,83 @@
X ~tvcards[btv->type].gpiomask2, BT848_GPIO_DATA);
X }
X
+/*
+ * Set the registers for the size we have specified. Don't bother
+ * trying to understand this without the BT848 manual in front of
+ * you [AC].
+ *
+ * PS: The manual is free for download in .pdf format from
+ * www.brooktree.com - nicely done those folks.
+ */
+
+struct tvnorm
+{
+ u32 Fsc;
+ u16 swidth, sheight; /* scaled standard width, height */
+ u16 totalwidth;
+ u8 adelay, bdelay, iform;
+ u32 scaledtwidth;
+ u16 hdelayx1, hactivex1;
+ u16 vdelay;
+ u8 vbipack;
+};
X
-#define VBIBUF_SIZE 65536
-
-/* Maximum sample number per VBI line is 2044, NTSC delivers 1600
- Note that we write 2048-aligned to keep alignment to memory pages
- VBI_RISC is written so that it applies to either 2044 or 1600
+static struct tvnorm tvnorms[] = {
+ /* PAL-BDGHI */
+ /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
+ /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
+#ifdef VIDEODAT
+ { 35468950,
+ 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+ 1135, 186, 924, 0x20, 255},
+#else
+ { 35468950,
+ 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+ 1135, 186, 924, 0x20, 255},
+#endif
+/*
+ { 35468950,
+ 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+ 944, 186, 922, 0x20, 255},
+*/
+ /* NTSC */
+ { 28636363,
+ 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+ 910, 128, 754, 0x1a, 144},
+/*
+ { 28636363,
+ 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+ 780, 122, 754, 0x1a, 144},
X */
+#if 0
+ /* SECAM EAST */
+ { 35468950,
+ 768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+ 944, 186, 922, 0x20, 255},
+#else
+ /* SECAM L */
+ { 35468950,
+ 924, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+ 1135, 186, 922, 0x20, 255},
+#endif
+ /* PAL-NC */
+ { 28636363,
+ 640, 576, 910, 0x68, 0x5d, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
+ 780, 130, 734, 0x1a, 144},
+ /* PAL-M */
+ { 28636363,
+ 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
+ 780, 135, 754, 0x1a, 144},
+ /* PAL-N */
+ { 35468950,
+ 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
+ 944, 186, 922, 0x20, 144},
+ /* NTSC-Japan */
+ { 28636363,
+ 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
+ 780, 135, 754, 0x16, 144},
+};
+#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
X #define VBI_SPL 2044
X
X /* RISC command to write one VBI data line */
@@ -661,7 +814,11 @@
X DEBUG(printk(KERN_DEBUG "vbievn: 0x%08x\n",(int)btv->vbi_even));
X DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po));
X DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe));
-
+
+ /* setup proper VBI capture length for given video mode */
+ btwrite(tvnorms[btv->win.norm].vbipack, BT848_VBI_PACK_SIZE);
+ btwrite(1, BT848_VBI_PACK_DEL);
+
X *(po++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(po++)=0;
X for (i=0; i<16; i++)
X {
@@ -697,12 +854,14 @@
X BT848_COLOR_FMT_RGB15,
X BT848_COLOR_FMT_YUY2,
X BT848_COLOR_FMT_BtYUV,
- 0,
- 0,
- 0,
+ -1,
+ -1,
+ -1,
X BT848_COLOR_FMT_RAW,
X BT848_COLOR_FMT_YCrCb422,
X BT848_COLOR_FMT_YCrCb411,
+ BT848_COLOR_FMT_YCrCb422,
+ BT848_COLOR_FMT_YCrCb411,
X };
X #define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int))
X
@@ -738,11 +897,120 @@
X }
X
X
-static int make_vrisctab(struct bttv *btv, unsigned int *ro,
+static int make_prisctab(struct bttv *btv, unsigned int *ro,
X unsigned int *re,
X unsigned int *vbuf, unsigned short width,
X unsigned short height, unsigned short fmt)
X {
+ unsigned long line, lmask;
+ unsigned long bl, blcr, blcb, rcmd;
+ unsigned long todo;
+ unsigned int **rp;
+ int inter;
+ unsigned long cbadr, cradr;
+ unsigned long vadr=(unsigned long) vbuf;
+ int shift, csize;
+
+
+ switch(fmt)
+ {
+ case VIDEO_PALETTE_YUV422P:
+ csize=(width*height)>>1;
+ shift=1;
+ lmask=0;
+ break;
+
+ case VIDEO_PALETTE_YUV411P:
+ csize=(width*height)>>2;
+ shift=2;
+ lmask=0;
+ break;
+
+ case VIDEO_PALETTE_YUV420P:
+ csize=(width*height)>>2;
+ shift=1;
+ lmask=1;
+ break;
+
+ case VIDEO_PALETTE_YUV410P:
+ csize=(width*height)>>4;
+ shift=2;
+ lmask=3;
+ break;
+
+ default:
+ return -1;
+ }
+ cbadr=vadr+(width*height);
+ cradr=cbadr+csize;
+ inter = (height>btv->win.cropheight/2) ? 1 : 0;
+
+ *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(ro++)=0;
+ *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(re++)=0;
+
+ for (line=0; line < (height<<(1^inter)); line++)
+ {
+ if(line==height)
+ {
+ vadr+=csize<<1;
+ cbadr=vadr+(width*height);
+ cradr=cbadr+csize;
+ }
+ if (inter)
+ rp= (line&1) ? &re : &ro;
+ else
+ rp= (line>=height) ? &re : &ro;
+
+
+ if(line&lmask)
+ rcmd=BT848_RISC_WRITE1S23|BT848_RISC_SOL;
+ else
+ rcmd=BT848_RISC_WRITE123|BT848_RISC_SOL;
+
+ todo=width;
+ while(todo)
+ {
+ bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);
+ blcr=(PAGE_SIZE-((PAGE_SIZE-1)&cradr))<<shift;
+ blcb=(PAGE_SIZE-((PAGE_SIZE-1)&cbadr))<<shift;
+ bl=(blcr<bl) ? blcr : bl;
+ bl=(blcb<bl) ? blcb : bl;
+ bl=(bl>todo) ? todo : bl;
+ blcr=bl>>shift;
+ blcb=blcr;
+ /* bl now containts the longest row that can be written */
+ todo-=bl;
+ if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */
+
+ *((*rp)++)=rcmd|bl;
+ *((*rp)++)=blcb|(blcr<<16);
+ *((*rp)++)=kvirt_to_bus(vadr);
+ vadr+=bl;
+ if((rcmd&(15<<28))==BT848_RISC_WRITE123)
+ {
+ *((*rp)++)=kvirt_to_bus(cbadr);
+ cbadr+=blcb;
+ *((*rp)++)=kvirt_to_bus(cradr);
+ cradr+=blcr;
+ }
+
+ rcmd&=~BT848_RISC_SOL; /* only the first has SOL */
+ }
+ }
+
+ *(ro++)=BT848_RISC_JUMP;
+ *(ro++)=btv->bus_vbi_even;
+ *(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16);
+ *(re++)=btv->bus_vbi_odd;
+

+ return 0;
+}
+

+static int make_vrisctab(struct bttv *btv, unsigned int *ro,
+ unsigned int *re,
+ unsigned int *vbuf, unsigned short width,
+ unsigned short height, unsigned short palette)
+{
X unsigned long line;
X unsigned long bpl; /* bytes per line */
X unsigned long bl;
@@ -751,11 +1019,14 @@
X int inter;
X unsigned long vadr=(unsigned long) vbuf;
X
- if (btv->gfmt==BT848_COLOR_FMT_RAW)
+ if (palette==VIDEO_PALETTE_RAW)
X return make_rawrisctab(btv, ro, re, vbuf);
+ if (palette>=VIDEO_PALETTE_PLANAR)
+ return make_prisctab(btv, ro, re, vbuf, width, height, palette);
+
X
X inter = (height>btv->win.cropheight/2) ? 1 : 0;
- bpl=width*fmtbppx2[fmt&0xf]/2;
+ bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2;
X
X *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
X *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
@@ -765,7 +1036,7 @@
X if (inter)
X rp= (line&1) ? &re : &ro;
X else
- rp= (line>height) ? &re : &ro;
+ rp= (line>=height) ? &re : &ro;
X
X bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);
X if (bpl<=bl)
@@ -803,16 +1074,62 @@
X return 0;
X }
X
+static unsigned char lmaskt[8] =
+{ 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
+static unsigned char rmaskt[8] =
+{ 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
X static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h)
X {
- int i, j;
+ unsigned char lmask, rmask, *p;
+ int W, l, r;
+ int i;
X /* bitmap is fixed width, 128 bytes (1024 pixels represented) */
- if (x < 0 || y < 0 || w < 0 || h < 0) /* catch bad clips */
+ if (x<0)
+ {
+ w+=x;
+ x=0;
+ }
+ if (y<0)
+ {
+ h+=y;
+ y=0;
+ }
+ if (w < 0 || h < 0) /* catch bad clips */
X return;
X /* out of range data should just fall through */
- for (i = y; i < y + h && i < 625; i++)
- for (j = x; j < x + w && j < 1024; j++)
- clipmap[(i<<7)+(j>>3)] |= (1<<(j&7));
+ if (y+h>=625)
+ h=625-y;
+ if (x+w>=1024)
+ w=1024-x;
+
+ l=x>>3;
+ r=(x+w)>>3;
+ W=r-l-1;
+ lmask=lmaskt[x&7];
+ rmask=rmaskt[(x+w)&7];
+ p=clipmap+128*y+l;
+
+ if (W>0)
+ {
+ for (i=0; i<h; i++, p+=128)
+ {
+ *p|=lmask;
+ memset(p+1, 0xff, W);
+ p[W+1]|=rmask;
+ }
+ } else if (!W) {
+ for (i=0; i<h; i++, p+=128)
+ {
+ p[0]|=lmask;
+ p[1]|=rmask;
+ }
+ } else {
+ for (i=0; i<h; i++, p+=128)
+ p[0]|=lmask&rmask;
+ }
+
+
X }
X
X static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
@@ -904,73 +1221,6 @@
X *(re++)=btv->bus_vbi_odd;
X }
X
-
-/*
- * Set the registers for the size we have specified. Don't bother
- * trying to understand this without the BT848 manual in front of
- * you [AC].
- *
- * PS: The manual is free for download in .pdf format from
- * www.brooktree.com - nicely done those folks.
- */
-
-struct tvnorm
-{
- u32 Fsc;
- u16 swidth, sheight; /* scaled standard width, height */
- u16 totalwidth;
- u8 adelay, bdelay, iform;
- u32 scaledtwidth;
- u16 hdelayx1, hactivex1;
- u16 vdelay;
- u8 vbipack;
-};
-
-static struct tvnorm tvnorms[] = {
- /* PAL-BDGHI */
- /* max pal/secam is actually 922, but 924 is divisible by 4 and 3! */
- /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
- { 35468950,
- 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 1135, 178, 924, 0x20, 255},
-/*
- { 35468950,
- 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 944, 178, 922, 0x20, 255},
-*/
- /* NTSC */
- { 28636363,
- 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
- 910, 128, 754, 0x1a, 144},
-/*
- { 28636363,
- 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
- 780, 122, 754, 0x1a, 144},
-*/
- /* SECAM - phase means nothing in SECAM, bdelay is useless */
- { 35468950,
- 924, 576,1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
- 1135, 178, 924, 0x20, 255},
- /* PAL-M */
- { 28636363,
- 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
- 780, 122, 754, 0x1a, 144},
- /* PAL-N */
- { 35468950,
- 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
- 944, 178, 922, 0x20, 255},
- /* PAL-NC */
- { 35468950,
- 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
- 944, 178, 922, 0x20, 255},
- /* NTSC-Japan */
- { 28636363,
- 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
- 780, 122, 754, 0x1a, 144},
-};
-#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
-
-
X /* set geometry for even/odd frames
X just if you are wondering:
X handling of even and odd frames will be separated, e.g. for grabbing
@@ -1031,10 +1281,9 @@
X btwrite(tvn->adelay, BT848_ADELAY);
X btwrite(tvn->bdelay, BT848_BDELAY);
X btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
- btwrite(1, BT848_VBI_PACK_DEL);
- btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE);
-
- set_pll(btv);
+
+ btv->pll.pll_ofreq = tvn->Fsc;
+ set_pll(btv);
X
X btwrite(fmt, BT848_COLOR_FMT);
X hactive=width;
@@ -1065,7 +1314,6 @@
X hdelay, vdelay, crop);
X bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, vactive,
X hdelay, vdelay, crop);
-
X }
X
X
@@ -1105,35 +1353,34 @@
X {
X int fixme = freq; /* XXX */
X
- if (btv->radio)
- {
- if (btv->have_tuner)
+ /* mute */
+ if (btv->have_msp3400)
+ i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
+ MSP_SWITCH_MUTE,0);
+
+ /* switch channel */
+ if (btv->have_tuner) {
+ if (btv->radio) {
X i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
X TUNER_SET_RADIOFREQ,&fixme);
-
- if (btv->have_msp3400) {
- i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
- MSP_SET_RADIO,0);
- i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
- MSP_NEWCHANNEL,0);
- }
- }
- else
- {
- if (btv->have_tuner)
+ } else {
X i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
X TUNER_SET_TVFREQ,&fixme);
+ }
+ }
X
- if (btv->have_msp3400) {
+ if (btv->have_msp3400) {
+ if (btv->radio) {
+ i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
+ MSP_SET_RADIO,0);
+ } else {
X i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
X MSP_SET_TVNORM,&(btv->win.norm));
X i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
X MSP_NEWCHANNEL,0);
- }
- }
-
+ }
+ }
X }
-
X
X /*
X * Grab into virtual memory.
@@ -1172,12 +1419,12 @@
X */
X if (mp->format >= PALETTEFMT_MAX)
X return -EINVAL;
- if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2
- > BTTV_MAX_FBUF)
+ if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2
+ > BTTV_MAX_FBUF)
X return -EINVAL;
- if (!palette2fmt[mp->format])
+ if(-1 == palette2fmt[mp->format])
X return -EINVAL;
-
+
X /*
X * FIXME: Check the format of the grab here. This is probably
X * also less restrictive than the normal overlay grabs. Stuff
@@ -1193,7 +1440,7 @@
X return -EAGAIN;*/
X ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0);
X re=ro+2048;
- make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, palette2fmt[mp->format]);
+ make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format);
X /* bt848_set_risc_jmps(btv); */
X btv->frame_stat[mp->frame] = GBUFFER_GRABBING;
X if (btv->grabbing) {
@@ -1211,8 +1458,13 @@
X btv->gre=virt_to_bus(re);
X btv->grf=mp->frame;
X }
- if (!(btv->grabbing++))
+ if (!(btv->grabbing++)) {
+ if(mp->format>=VIDEO_PALETTE_COMPONENT) {
+ btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI);
+ btor(BT848_VSCALE_COMB, BT848_O_VSCALE_HI);
+ }
X btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ;
+ }
X btor(3, BT848_CAP_CTL);
X btor(3, BT848_GPIO_DMA_CTL);
X /* interruptible_sleep_on(&btv->capq); */
@@ -1228,7 +1480,7 @@
X {
X struct bttv *btv= (struct bttv *)v;
X int q,todo;
-
+ /* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */
X todo=count;
X while (todo && todo>(q=VBIBUF_SIZE-btv->vbip))
X {
@@ -1276,36 +1528,27 @@
X struct bttv *btv = (struct bttv *)dev;
X int users, i;
X
- switch (flags)
- {
- case 0:
- if (btv->user)
- return -EBUSY;
- btv->user++;
- audio(btv, AUDIO_UNMUTE);
- for (i=users=0; i<bttv_num; i++)
- users+=bttvs[i].user;
- if (users==1)
- find_vga();
- btv->fbuffer=NULL;
- if (!btv->fbuffer)
- btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
- if (!btv->fbuffer)
- {
- btv->user--;
- return -EINVAL;
- }
- btv->grabbing = 0;
- btv->grab = 0;
- btv->lastgrab = 0;
- for (i = 0; i < MAX_GBUFFERS; i++)
- btv->frame_stat[i] = GBUFFER_UNUSED;
- break;
- case 1:
- break;
- }
- MOD_INC_USE_COUNT;
- return 0;
+ if (btv->user)
+ return -EBUSY;
+ audio(btv, AUDIO_UNMUTE);
+ for (i=users=0; i<bttv_num; i++)
+ users+=bttvs[i].user;
+ if (users==1)
+ find_vga();
+ btv->fbuffer=NULL;
+ if (!btv->fbuffer)
+ btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
+ if (!btv->fbuffer)
+ return -EINVAL;
+ btv->grabbing = 0;
+ btv->grab = 0;
+ btv->lastgrab = 0;
+ for (i = 0; i < MAX_GBUFFERS; i++)
+ btv->frame_stat[i] = GBUFFER_UNUSED;
+
+ btv->user++;
+ MOD_INC_USE_COUNT;
+ return 0;
X }
X
X static void bttv_close(struct video_device *dev)
@@ -1394,8 +1637,8 @@
X VID_TYPE_SCALES;
X b.channels = tvcards[btv->type].video_inputs;
X b.audios = tvcards[btv->type].audio_inputs;
- b.maxwidth = 768;
- b.maxheight = 576;
+ b.maxwidth = tvnorms[btv->win.norm].swidth;
+ b.maxheight = tvnorms[btv->win.norm].sheight;
X b.minwidth = 32;
X b.minheight = 32;
X if(copy_to_user(arg,&b,sizeof(b)))
@@ -1421,7 +1664,7 @@
X v.tuners=1;
X }
X else if(v.channel==tvcards[btv->type].svhs)
- strcpy(v.name,"SVHS");
+ strcpy(v.name,"S-Video");
X else
X sprintf(v.name,"Composite%d",v.channel);
X
@@ -1438,14 +1681,14 @@
X if(copy_from_user(&v, arg,sizeof(v)))
X return -EFAULT;
X
- if (v.channel>=tvcards[btv->type].video_inputs)
+ if (v.channel>tvcards[btv->type].video_inputs)
X return -EINVAL;
X bt848_muxsel(btv, v.channel);
X if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC
X &&v.norm!=VIDEO_MODE_SECAM)
X return -EOPNOTSUPP;
X btv->win.norm = v.norm;
- make_vbitab(btv);
+ make_vbitab(btv);
X bt848_set_winsize(btv);
X btv->channel=v.channel;
X return 0;
@@ -1461,6 +1704,11 @@
X v.rangelow=0;
X v.rangehigh=0xFFFFFFFF;
X v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
+ if (btv->audio_chip == TDA9840) {
+ v.flags |= VIDEO_AUDIO_VOLUME;
+ v.mode = VIDEO_SOUND_MONO|VIDEO_SOUND_STEREO;
+ v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2;
+ }
X if (btv->audio_chip == TDA9850) {
X unsigned char ALR1;
X ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);
@@ -1479,7 +1727,6 @@
X struct video_tuner v;
X if(copy_from_user(&v, arg, sizeof(v)))
X return -EFAULT;
-
X /* Only one channel has a tuner */
X if(v.tuner!=tvcards[btv->type].tuner)
X return -EINVAL;
@@ -1543,13 +1790,17 @@
X if(copy_from_user(&vw,arg,sizeof(vw)))
X return -EFAULT;
X
- if(vw.flags || vw.width < 16 || vw.height < 16) {
- bt848_cap(btv,0);
+ if(vw.flags || vw.width < 16 || vw.height < 16)
+ {
+ bt848_cap(btv,0);
X return -EINVAL;
- }
- if (btv->win.bpp < 4) { /* adjust and align writes */
+ }
+ if (btv->win.bpp < 4)
+ { /* 32-bit align start and adjust width */
+ int i = vw.x;
X vw.x = (vw.x + 3) & ~3;
- vw.width = (vw.width - 3) & ~3;
+ i = vw.x - i;
+ vw.width -= i;
X }
X btv->win.x=vw.x;
X btv->win.y=vw.y;
@@ -1591,7 +1842,7 @@
X make_clip_tab(btv, vcp, vw.clipcount);
X if (vw.clipcount != 0)
X vfree(vcp);
- if(on && btv->win.vidadr != 0)
+ if(on && btv->win.vidadr!=0)
X bt848_cap(btv,1);
X return 0;
X }
@@ -1645,7 +1896,11 @@
X case VIDIOCSFBUF:
X {
X struct video_buffer v;
+#if LINUX_VERSION_CODE >= 0x020100
X if(!capable(CAP_SYS_ADMIN))
+#else
+ if(!suser())
+#endif
X return -EPERM;
X if(copy_from_user(&v, arg,sizeof(v)))
X return -EFAULT;
@@ -1653,7 +1908,13 @@
X v.depth!=24 && v.depth!=32 && v.width > 16 &&
X v.height > 16 && v.bytesperline > 16)
X return -EINVAL;
- btv->win.vidadr=(unsigned long)v.base;
+ if (v.base)
+ {
+ if ((unsigned long)v.base&1)
+ btv->win.vidadr=(unsigned long)(PAGE_OFFSET|uvirt_to_bus((unsigned long)v.base));
+ else
+ btv->win.vidadr=(unsigned long)v.base;
+ }
X btv->win.sheight=v.height;
X btv->win.swidth=v.width;
X btv->win.bpp=((v.depth+7)&0x38)/8;
@@ -1696,15 +1957,13 @@
X strcpy(v.name,"TV");
X if (btv->audio_chip == TDA9850) {
X unsigned char ALR1;
- v.flags|=VIDEO_AUDIO_VOLUME;
X ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);
X v.mode = VIDEO_SOUND_MONO;
X v.mode |= (ALR1 & 32) ? VIDEO_SOUND_STEREO:0;
- v.mode |= (ALR1 & 32) ? VIDEO_SOUND_LANG1:0;
- v.volume = 32768; /* fixme */
- v.step = 4096;
+ v.mode |= (ALR1 & 64) ? VIDEO_SOUND_LANG1:0;
X }
- else if (btv->have_msp3400) {
+ if (btv->have_msp3400)
+ {
X v.flags|=VIDEO_AUDIO_VOLUME |
X VIDEO_AUDIO_BASS |
X VIDEO_AUDIO_TREBLE;
@@ -1735,9 +1994,8 @@
X audio(btv, AUDIO_MUTE);
X /* One audio source per tuner */
X /* if(v.audio!=0) */
- /* Nope... I have three on my ADSTech TV card. The*/
- /* ADSTech TV+FM prolly has 4 <rri...@tesser.com> */
- if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)
+ /* ADSTech TV card has more than one */
+ if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)
X return -EINVAL;
X bt848_muxsel(btv,v.audio);
X if(!(v.flags&VIDEO_AUDIO_MUTE))
@@ -1750,12 +2008,9 @@
X con3 = 0x40; /* stereo */
X I2CWrite(&(btv->i2c), I2C_TDA9850,
X TDA9850_CON3, con3, 1);
- if (v.flags & VIDEO_AUDIO_VOLUME)
- I2CWrite(&(btv->i2c), I2C_TDA9850,
- TDA9850_CON4,
- (v.volume>>12) & 15, 1);
X }
- else if (btv->have_msp3400) {
+ if (btv->have_msp3400)
+ {
X i2c_control_device(&(btv->i2c),
X I2C_DRIVERID_MSP3400,
X MSP_SET_VOLUME,&(v.volume));
@@ -1776,13 +2031,18 @@
X case VIDIOCSYNC:
X if(copy_from_user((void *)&i,arg,sizeof(int)))
X return -EFAULT;
- if (i>1 || i<0)
- return -EINVAL;
+/* if(i>1 || i<0)
+ return -EINVAL;
+*/
X switch (btv->frame_stat[i]) {
X case GBUFFER_UNUSED:
X return -EINVAL;
X case GBUFFER_GRABBING:
- interruptible_sleep_on(&btv->capq);
+ while(btv->frame_stat[i]==GBUFFER_GRABBING) {
+ interruptible_sleep_on(&btv->capq);
+ if(signal_pending(current))
+ return -EINTR;
+ }
X /* fall */
X case GBUFFER_DONE:
X btv->frame_stat[i] = GBUFFER_UNUSED;
@@ -1791,7 +2051,11 @@
X return 0;
X
X case BTTV_WRITEE:
+#if LINUX_VERSION_CODE >= 0x020100
X if(!capable(CAP_SYS_ADMIN))
+#else
+ if(!suser())
+#endif
X return -EPERM;
X if(copy_from_user((void *) eedata, (void *) arg, 256))
X return -EFAULT;
@@ -1799,32 +2063,39 @@
X return 0;
X
X case BTTV_READEE:
+#if LINUX_VERSION_CODE >= 0x020100
X if(!capable(CAP_SYS_ADMIN))
+#else
+ if(!suser())
+#endif
X return -EPERM;
X readee(&(btv->i2c), eedata);
X if(copy_to_user((void *) arg, (void *) eedata, 256))
X return -EFAULT;
X break;
X
- case BTTV_FIELDNR:
+ case BTTV_FIELDNR:
X if(copy_to_user((void *) arg, (void *) &btv->last_field,
X sizeof(btv->last_field)))
X return -EFAULT;
X break;
-
- case BTTV_PLLSET:
- {
- struct bttv_pll_info p;
+
+ case BTTV_PLLSET: {
+ struct bttv_pll_info p;
+#if LINUX_VERSION_CODE >= 0x020100
X if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
+#else
+ if(!suser())
+#endif
+ return -EPERM;
+ if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
X return -EFAULT;
- btv->pll.pll_ifreq = p.pll_ifreq;
- btv->pll.pll_ofreq = p.pll_ofreq;
- btv->pll.pll_crystal = p.pll_crystal;
- break;
- }
+ btv->pll.pll_ifreq = p.pll_ifreq;
+ btv->pll.pll_ofreq = p.pll_ofreq;
+ btv->pll.pll_crystal = p.pll_crystal;
X
+ break;
+ }
X case VIDIOCMCAPTURE:
X {
X struct video_mmap vm;
@@ -1868,7 +2139,7 @@
X return -EFAULT;
X return 0;
X }
-
+
X case BTTV_BURST_ON:
X {
X tvnorms[0].scaledtwidth=1135-BURSTOFFSET-2;
@@ -1883,9 +2154,14 @@
X return 0;
X }
X
+ case BTTV_VERSION:
+ {
+ return BTTV_VERSION_CODE;
+ }
+
X case BTTV_PICNR:
X {
- /* return picture */
+ /* return picture;*/
X return 0;
X }
X
@@ -1944,7 +2220,9 @@
X bttv_close,
X bttv_read,
X bttv_write,
+#if LINUX_VERSION_CODE >= 0x020100
X NULL, /* poll */
+#endif
X bttv_ioctl,
X bttv_mmap,
X bttv_init_done,
@@ -1998,6 +2276,7 @@
X return count;
X }


X
+#if LINUX_VERSION_CODE >= 0x020100

X static unsigned int vbi_poll(struct video_device *dev, struct file *file,
X poll_table *wait)
X {
@@ -2011,6 +2290,7 @@
X
X return mask;
X }
+#endif
X
X static int vbi_open(struct video_device *dev, int flags)
X {
@@ -2049,7 +2329,9 @@
X vbi_close,
X vbi_read,
X bttv_write,
+#if LINUX_VERSION_CODE >= 0x020100
X vbi_poll,
+#endif
X vbi_ioctl,
X NULL, /* no mmap yet */
X bttv_init_done,
@@ -2159,7 +2441,9 @@
X radio_close,
X radio_read, /* just returns -EINVAL */
X bttv_write, /* just returns -EINVAL */
+#if LINUX_VERSION_CODE >= 0x020100
X NULL, /* no poll */
+#endif
X radio_ioctl,
X NULL, /* no mmap */
X bttv_init_done, /* just returns 0 */
@@ -2177,14 +2461,14 @@
X };
X
X static struct vidbases vbs[] = {
- { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D,
- "Alliance AT3D", PCI_BASE_ADDRESS_0},
+ { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D,
+ "Alliance AT3D", PCI_BASE_ADDRESS_0},
X { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215CT222,
X "ATI MACH64 CT", PCI_BASE_ADDRESS_0},
X { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX,
X "ATI MACH64 Winturbo", PCI_BASE_ADDRESS_0},
X { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215GT,
- "ATI MACH64 GT", PCI_BASE_ADDRESS_0},
+ "ATI MACH64 GT", PCI_BASE_ADDRESS_0},
X { PCI_VENDOR_ID_CIRRUS, 0, "Cirrus Logic", PCI_BASE_ADDRESS_0},
X { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,
X "DEC DC21030", PCI_BASE_ADDRESS_0},
@@ -2195,6 +2479,7 @@
X { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP,
X "Matrox Millennium II AGP", PCI_BASE_ADDRESS_0},
X { PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1},
+ { PCI_VENDOR_ID_MATROX, 0x0521, "Matrox G200", PCI_BASE_ADDRESS_0},
X { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128,
X "Number Nine Imagine 128", PCI_BASE_ADDRESS_0},
X { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128_2,
@@ -2220,6 +2505,8 @@
X /* Scan for PCI display adapter
X if more than one card is present the last one is used for now */
X
+#if LINUX_VERSION_CODE >= 0x020100
+
X static int find_vga(void)
X {
X unsigned short badr;
@@ -2299,6 +2586,99 @@
X return found;
X }
X
+#else
+static int find_vga(void)
+{
+ unsigned int devfn, class, vendev;
+ unsigned short vendor, device, badr;
+ int found=0, bus=0, i, tga_type;
+ unsigned int vidadr=0;
+
+
+ for (devfn = 0; devfn < 0xff; devfn++)
+ {
+ if (PCI_FUNC(devfn) != 0)
+ continue;
+ pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendev);
+ if (vendev == 0xffffffff || vendev == 0x00000000)
+ continue;
+ pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &device);
+ pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class);
+ class = class >> 16;
+/* if (class == PCI_CLASS_DISPLAY_VGA) {*/
+ if ((class>>8) == PCI_BASE_CLASS_DISPLAY ||
+ /* Number 9 GXE64Pro needs this */
+ class == PCI_CLASS_NOT_DEFINED_VGA)
+ {
+ badr=0;
+ printk(KERN_INFO "bttv: PCI display adapter: ");
+ for (i=0; i<NR_CARDS; i++)
+ {
+ if (vendor==vbs[i].vendor)
+ {
+ if (vbs[i].device)
+ if (vbs[i].device!=device)
+ continue;
+ printk("%s.\n", vbs[i].name);
+ badr=vbs[i].badr;
+ break;
+ }
+ }
+ if (NR_CARDS == i)
+ printk("UNKNOWN.\n");
+ if (!badr)
+ {
+ printk(KERN_ERR "bttv: Unknown video memory base address.\n");
+ continue;
+ }
+ pcibios_read_config_dword(bus, devfn, badr, &vidadr);
+ if (vidadr & PCI_BASE_ADDRESS_SPACE_IO)
+ {
+ printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n");
+ printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n");
+ continue;
+ }
+ vidadr &= PCI_BASE_ADDRESS_MEM_MASK;
+ if (!vidadr)
+ {
+ printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!\n");
+ continue;
+ }
+
+ if (vendor==PCI_VENDOR_ID_DEC)
+ if (device==PCI_DEVICE_ID_DEC_TGA)
+ {
+ tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f;
+ if (tga_type != 0 && tga_type != 1 && tga_type != 3)
+ {
+ printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type);
+ found--;
+ }
+ vidadr+=dec_offsets[tga_type];
+ }
+
+ DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr));
+ DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", devfn));
+ found++;
+ }
+ }
+
+ if (vidmem)
+ {
+ if (vidmem < 0x1000)
+ vidadr=vidmem<<20;
+ else
+ vidadr=vidmem;
+ printk(KERN_INFO "bttv: Video memory override: 0x%08x\n", vidadr);
+ found=1;
+ }
+ for (i=0; i<BTTV_MAX; i++)
+ bttvs[i].win.vidadr=vidadr;
+
+ return found;
+}
+#endif
X
X
X #define TRITON_PCON 0x50
@@ -2307,6 +2687,9 @@
X #define TRITON_WRITE_BURST (1<<2)
X #define TRITON_PEER_CONCURRENCY (1<<3)
X

+
+#if LINUX_VERSION_CODE >= 0x020100

+
X static void handle_chipset(void)
X {
X struct pci_dev *dev = NULL;
@@ -2370,6 +2753,78 @@
X #endif
X }
X }
+#else
+static void handle_chipset(void)
+{
+ int index;
+
+ for (index = 0; index < 8; index++)
+ {
+ unsigned char bus, devfn;
+ unsigned char b;
+
+ /* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */
+
+ if (!pcibios_find_device(PCI_VENDOR_ID_SI,
+ PCI_DEVICE_ID_SI_496,
+ index, &bus, &devfn))
+ {
+ printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n");
+ }
+
+ if (!pcibios_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82441,
+ index, &bus, &devfn))
+ {
+ pcibios_read_config_byte(bus, devfn, 0x53, &b);
+ DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
+ DEBUG(printk("bufcon=0x%02x\n",b));
+ }
+
+ if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437,
+ index, &bus, &devfn))
+ {
+ printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n");
+ triton1=BT848_INT_ETBF;
+
+#if 0
+ /* The ETBF bit SHOULD make all this unnecessary */
+ /* 430FX (Triton I) freezes with bus concurrency on -> switch it off */
+ {
+ unsigned char bo;
+
+ pcibios_read_config_byte(bus, devfn, TRITON_PCON, &b);
+ bo=b;
+ DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b));
+
+ if(!(b & TRITON_BUS_CONCURRENCY))
+ {
+ printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n");
+ b |= TRITON_BUS_CONCURRENCY;
+ }
+
+ if(b & TRITON_PEER_CONCURRENCY)
+ {
+ printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n");
+ b &= ~TRITON_PEER_CONCURRENCY;
+ }
+ if(!(b & TRITON_STREAMING))
+ {
+ printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n");
+ b |= TRITON_STREAMING;
+ }
+
+ if (b!=bo)
+ {
+ pcibios_write_config_byte(bus, devfn, TRITON_PCON, b);
+ printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b);
+ }
+ }
+#endif
+ }
+ }
+}
+#endif
X
X static void init_tda8425(struct i2c_bus *bus)
X {
@@ -2377,9 +2832,13 @@
X I2CWrite(bus, I2C_TDA8425, TDA8425_VR, 0xFC, 1); /* volume right 0dB */
X I2CWrite(bus, I2C_TDA8425, TDA8425_BA, 0xF6, 1); /* bass 0dB */
X I2CWrite(bus, I2C_TDA8425, TDA8425_TR, 0xF6, 1); /* treble 0dB */
- I2CWrite(bus, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */
+ I2CWrite(bus, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */
X }
X
+static void init_tda9840(struct i2c_bus *bus)
+{
+ I2CWrite(bus, I2C_TDA9840, TDA9840_SW, 0x2A, 1); /* Sound mode switching */
+}
X
X static void init_tda9850(struct i2c_bus *bus)
X {
@@ -2400,7 +2859,6 @@
X {
X struct bttv *btv = &bttvs[i];
X
- int tunertype;
X btwrite(0, BT848_GPIO_OUT_EN);
X DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA)));
X
@@ -2413,99 +2871,115 @@
X */
X if (btv->type == BTTV_UNKNOWN)
X {
- btv->type=BTTV_MIRO;
-
- if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0) {
+ if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0)
+ {
X if(btv->id>849)
- {
X btv->type=BTTV_HAUPPAUGE878;
- btv->pll.pll_ifreq = 28636363;
- btv->pll.pll_crystal = BT848_IFORM_XT0;
- }
X else
- btv->type=BTTV_HAUPPAUGE;
- }
- else
- if (I2CRead(&(btv->i2c), I2C_STBEE)>=0)
- btv->type=BTTV_STB;
+ btv->type=BTTV_HAUPPAUGE;
X
- if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) {
- /* auto detect tuner for MIRO cards */
- btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
- }
+ } else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) {
+ btv->type=BTTV_STB;
+
+ } else {
+ if (I2CRead(&(btv->i2c), 0x80)>=0) /* check for msp34xx */
+ btv->type = BTTV_MIROPRO;
+ else
+ btv->type=BTTV_MIRO;
+ }
X }
X
+ /* board specific initialisations */
+ if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) {
+ /* auto detect tuner for MIRO cards */
+ btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+ }
+ if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) {
+ hauppauge_msp_reset(btv);
+ hauppauge_eeprom(&(btv->i2c));
+ if (btv->type == BTTV_HAUPPAUGE878) {
+ /* all bt878 hauppauge boards use this ... */
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
+ }
+ }
+ if(btv->type==BTTV_AVERMEDIA98)
+ {
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
+ }
+
+ if (btv->have_tuner && btv->tuner_type != -1)
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_TUNER,
+ TUNER_SET_TYPE,&btv->tuner_type);
+
+
+ if (I2CRead(&(btv->i2c), I2C_TDA9840) >=0)
+ {
+ btv->audio_chip = TDA9840;
+ printk(KERN_INFO "bttv%d: audio chip: TDA9840\n", btv->nr);
+ }
+
X if (I2CRead(&(btv->i2c), I2C_TDA9850) >=0)
X {
- btv->audio_chip = TDA9850;
- printk(KERN_INFO "bttv%d: audio chip: TDA9850\n", i);
+ btv->audio_chip = TDA9850;
+ printk(KERN_INFO "bttv%d: audio chip: TDA9850\n",btv->nr);
X }
X
X if (I2CRead(&(btv->i2c), I2C_TDA8425) >=0)
X {
- btv->audio_chip = TDA8425;
- printk("bttv%d: audio chip: TDA8425\n", i);
+ btv->audio_chip = TDA8425;
+ printk(KERN_INFO "bttv%d: audio chip: TDA8425\n",btv->nr);
X }
X
X switch(btv->audio_chip)
X {
X case TDA9850:
X init_tda9850(&(btv->i2c));
- break;
- case TDA8425:
+ break;
+ case TDA8425:
X init_tda8425(&(btv->i2c));
X break;
X }
+
+ printk(KERN_INFO "bttv%d: model: ",btv->nr);
X
- /* How do I detect the tuner type for other cards but Miro ??? */
- printk(KERN_INFO "bttv%d: model: ", btv->nr);
X sprintf(btv->video_dev.name,"BT%d",btv->id);
X switch (btv->type)
X {
- case BTTV_MIRO:
- case BTTV_MIROPRO:
- printk("MIRO\n");
- if (btv->have_tuner)
- {
- tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7;
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_TUNER,
- TUNER_SET_TYPE,&tunertype);
- }
- strcat(btv->video_dev.name,"(Miro)");
+ case BTTV_MIRO:
+ case BTTV_MIROPRO:
+ strcat(btv->video_dev.name,
+ (btv->type == BTTV_MIRO) ? "(Miro)" : "(Miro pro)");
X break;
X case BTTV_HAUPPAUGE:
+ strcat(btv->video_dev.name,"(Hauppauge old)");
+ break;
X case BTTV_HAUPPAUGE878:
- printk("HAUPPAUGE\n");
- strcat(btv->video_dev.name,"(Hauppauge)");
+ strcat(btv->video_dev.name,"(Hauppauge new)");
X break;
X case BTTV_STB:
- printk("STB\n");
X strcat(btv->video_dev.name,"(STB)");
X break;
X case BTTV_INTEL:
- printk("Intel\n");
X strcat(btv->video_dev.name,"(Intel)");
X break;
X case BTTV_DIAMOND:
- printk("Diamond\n");
X strcat(btv->video_dev.name,"(Diamond)");
X break;
X case BTTV_AVERMEDIA:
- printk("AVerMedia\n");
X strcat(btv->video_dev.name,"(AVerMedia)");
X break;
X case BTTV_MATRIX_VISION:
- printk("MATRIX-Vision\n");
X strcat(btv->video_dev.name,"(MATRIX-Vision)");
X break;
- case BTTV_ADSTECH_TV:
- printk("ADSTech Channel Surfer TV\n");
- strcat(btv->video_dev.name,"(ADSTech Channel Surfer TV)");
- btv->tuner_type=8;
+ case BTTV_AVERMEDIA98:
+ strcat(btv->video_dev.name,"(AVerMedia TVCapture 98)");
X break;
X }
- audio(btv, AUDIO_INTERN);
+ printk("%s\n",btv->video_dev.name);
+ audio(btv, AUDIO_MUTE);
X }
X
X
@@ -2554,7 +3028,7 @@
X btv->risc_jmp[12]=BT848_RISC_JUMP;
X btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp);
X
- /* enable capturing and DMA */
+ /* enable cpaturing and DMA */
X btaor(flags, ~0x0f, BT848_CAP_CTL);
X if (flags&0x0f)
X bt848_dma(btv, 3);
@@ -2562,7 +3036,6 @@
X bt848_dma(btv, 0);
X }
X
-
X static int init_bt848(int i)
X {
X struct bttv *btv = &bttvs[i];
@@ -2573,19 +3046,7 @@
X btwrite(0, BT848_SRESET);
X DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%08x\n",i,(unsigned int) btv->bt848_mem));
X
-#ifdef RESET_MSP_HAUPPAUGE
- /* Reset the MSP on some Hauppauge cards */
- /* Thanks to Kyösti Mälkki (kma...@cc.hut.fi)! */
- /* Can this hurt cards without one? What about Miros with MSP? */
- btaor(32, ~32, BT848_GPIO_OUT_EN);
- btaor(0, ~32, BT848_GPIO_DATA);
- udelay(2500);
- btaor(32, ~32, BT848_GPIO_DATA);
- btaor(0, ~32, BT848_GPIO_OUT_EN);
-#endif
-
X /* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */
-
X btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */
X btv->win.interlace=1;
X btv->win.x=0;
@@ -2615,12 +3076,12 @@
X btv->grab=0;
X btv->lastgrab=0;
X btv->field=btv->last_field=0;
- /* cevans - prevents panic if initialization bails due to memory
- * alloc failures!
- */
- btv->video_dev.minor = -1;
- btv->vbi_dev.minor = -1;
- btv->radio_dev.minor = -1;
+ /* cevans - prevents panic if initialization bails due to memory
+ * alloc failures!
+ */
+ btv->video_dev.minor = -1;
+ btv->vbi_dev.minor = -1;
+ btv->radio_dev.minor = -1;
X
X /* i2c */
X memcpy(&(btv->i2c),&bttv_i2c_bus_template,sizeof(struct i2c_bus));
@@ -2648,6 +3109,7 @@
X
X memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random
X memory to the user */
+
X btv->fbuffer=NULL;
X
X bt848_muxsel(btv, 1);
@@ -2656,7 +3118,7 @@
X /* btwrite(0, BT848_TDEC); */
X btwrite(0x10, BT848_COLOR_CTL);
X btwrite(0x00, BT848_CAP_CTL);
- btwrite(0xfc, BT848_GPIO_DMA_CTL);
+ btwrite(0xac, BT848_GPIO_DMA_CTL);
X
X /* select direct input */
X btwrite(0x00, BT848_GPIO_REG_INP);
@@ -2706,6 +3168,7 @@
X memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template));
X memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template));
X memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template));
+
X idcard(i);
X
X if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
@@ -2765,7 +3228,7 @@
X if (astat&BT848_INT_VSYNC)
X {
X IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr));
- btv->field++;
+ btv->field++;
X }
X if (astat&BT848_INT_SCERR) {
X IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr));
@@ -2791,8 +3254,9 @@
X /* captured full frame */
X if (stat&(2<<28))
X {
+ wake_up_interruptible(&btv->capq);
X btv->last_field=btv->field;
- btv->grab++;
+ btv->grab++;
X btv->frame_stat[btv->grf] = GBUFFER_DONE;
X if ((--btv->grabbing))
X {
@@ -2809,7 +3273,9 @@
X btv->gfmt);
X } else {
X bt848_set_risc_jmps(btv);
- bt848_set_geo(btv, btv->win.width,
+ btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI);
+ btand(~BT848_VSCALE_COMB, BT848_O_VSCALE_HI);
+ bt848_set_geo(btv, btv->win.width,
X btv->win.height,
X btv->win.color_fmt);
X }
@@ -2855,12 +3321,10 @@
X }
X if (astat&BT848_INT_HLOCK)
X {
-#if 0
X if ((dstat&BT848_DSTATUS_HLOC) || (btv->radio))
X audio(btv, AUDIO_ON);
X else
X audio(btv, AUDIO_OFF);
-#endif
X }
X
X if (astat&BT848_INT_I2CDONE)
@@ -2869,7 +3333,8 @@
X
X count++;
X if (count > 10)
- printk (KERN_WARNING "bttv%d: irq loop %d\n", btv->nr, count);
+ printk (KERN_WARNING "bttv%d: irq loop %d\n",
+ btv->nr,count);
X if (count > 20)
X {
X btwrite(0, BT848_INT_MASK);
@@ -2885,17 +3350,16 @@
X * Scan for a Bt848 card, request the irq and map the io memory
X */
X
+#if LINUX_VERSION_CODE >= 0x020100
X int configure_bt848(struct pci_dev *dev, int bttv_num)
X {
X int result;
- unsigned char bus, devfn, command;
+ unsigned char command;
X struct bttv *btv;
X
X btv=&bttvs[bttv_num];
X btv->dev=dev;
X btv->nr = bttv_num;
- btv->bus=bus=dev->bus->number;
- btv->devfn=devfn=dev->devfn;
X btv->bt848_mem=NULL;
X btv->vbibuf=NULL;
X btv->risc_jmp=NULL;
@@ -2931,15 +3395,14 @@
X pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
X printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ",
X bttv_num,btv->id, btv->revision);
- printk("bus: %d, devfn: %d, ",
- btv->bus, btv->devfn);
+ printk("bus: %d, devfn: %d, ",dev->bus->number, dev->devfn);
X printk("irq: %d, ",btv->irq);
X printk("memory: 0x%08x.\n", btv->bt848_adr);
-
- btv->pll.pll_ifreq=0;
- btv->pll.pll_ofreq=0;
- btv->pll.pll_crystal=0;
- btv->pll.pll_current=0;
+
+ btv->pll.pll_crystal = 0;
+ btv->pll.pll_ifreq = 0;
+ btv->pll.pll_ofreq = 0;
+ btv->pll.pll_current = 0;
X if (!(btv->id==848 && btv->revision==0x11)) {
X switch (pll[btv->nr]) {
X case 0:
@@ -2957,10 +3420,10 @@
X break;
X }
X }
-
+
X btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
X
- /* clear interrupt mask */
+ /* clear interrupt mask */
X btwrite(0, BT848_INT_MASK);
X
X result = request_irq(btv->irq, bttv_irq,
@@ -3023,7 +3486,170 @@
X printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
X return bttv_num;
X }
-
+#else
+static int find_bt848(void)
+{
+ short pci_index;
+ unsigned char command, latency;
+ int result;
+ unsigned char bus, devfn;
+ struct bttv *btv;
+
+ bttv_num=0;
+
+ if (!pcibios_present())
+ {
+ DEBUG(printk(KERN_DEBUG "bttv%d: PCI-BIOS not present or not accessable!\n",bttv_num));


+ return 0;
+ }
+

+ for (pci_index = 0;
+ !pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
+ pci_index, &bus, &devfn)
+ ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
+ pci_index, &bus, &devfn)
+ ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878,
+ pci_index, &bus, &devfn)
+ ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879,
+ pci_index, &bus, &devfn);
+ ++pci_index)
+ {
+ btv=&bttvs[bttv_num];
+ btv->nr = bttv_num;
+ btv->bus=bus;
+ btv->devfn=devfn;
+ btv->bt848_mem=NULL;
+ btv->vbibuf=NULL;
+ btv->risc_jmp=NULL;
+ btv->vbi_odd=NULL;
+ btv->vbi_even=NULL;
+ btv->vbiq=NULL;
+ btv->capq=NULL;
+ btv->capqo=NULL;
+ btv->capqe=NULL;
+
+ btv->vbip=VBIBUF_SIZE;
+
+ pcibios_read_config_word(btv->bus, btv->devfn, PCI_DEVICE_ID,
+ &btv->id);
+ pcibios_read_config_byte(btv->bus, btv->devfn,
+ PCI_INTERRUPT_LINE, &btv->irq);
+ pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
+ &btv->bt848_adr);
+ if (btv->id >= 878)
+ btv->i2c_command = 0x83;
+ else
+ btv->i2c_command=
+ (I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA);
+
+ if (remap[bttv_num])
+ {
+ if (remap[bttv_num] < 0x1000)
+ remap[bttv_num]<<=20;
+ remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK;
+ printk(KERN_INFO "bttv%d: remapping to : 0x%08x.\n",
+ bttv_num,remap[bttv_num]);
+ remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK);
+ pcibios_write_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
+ remap[bttv_num]);
+ pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
+ &btv->bt848_adr);
+ }
+
+ btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_CLASS_REVISION,
+ &btv->revision);
+ printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ",
+ bttv_num,btv->id, btv->revision);
+ printk("bus: %d, devfn: %d, ",
+ btv->bus, btv->devfn);
+ printk("irq: %d, ",btv->irq);
+ printk("memory: 0x%08x.\n", btv->bt848_adr);
+
+ btv->pll.pll_crystal = 0;
+ btv->pll.pll_ifreq = 0;
+ btv->pll.pll_ofreq = 0;
+ btv->pll.pll_current = 0;
+ if (!(btv->id==848 && btv->revision==0x11)) {
+ switch (pll[btv->nr]) {
+ case 0:
+ /* off */
+ break;
+ case 1:
+ /* 28 MHz crystal installed */
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
+ break;
+ case 2:
+ /* 35 MHz crystal installed */
+ btv->pll.pll_ifreq=35468950;
+ btv->pll.pll_crystal=BT848_IFORM_XT1;
+ break;
+ }
+ }
+
+ btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
+
+ result = request_irq(btv->irq, bttv_irq,
+ SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv);
+ if (result==-EINVAL)
+ {
+ printk(KERN_ERR "bttv%d: Bad irq number or handler\n",
+ bttv_num);
+ return -EINVAL;
+ }
+ if (result==-EBUSY)
+ {
+ printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq);
+ return result;
+ }
+ if (result < 0)
+ return result;
+
+ /* Enable bus-mastering */
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
+ command|=PCI_COMMAND_MASTER;
+ pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
+ if (!(command&PCI_COMMAND_MASTER))
+ {
+ printk(KERN_ERR "bttv%d: PCI bus-mastering could not be enabled\n",bttv_num);
+ return -1;
+ }
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_LATENCY_TIMER,
+ &latency);
+ if (!latency)
+ {
+ latency=32;
+ pcibios_write_config_byte(btv->bus, btv->devfn,
+ PCI_LATENCY_TIMER, latency);
+ }
+ DEBUG(printk(KERN_DEBUG "bttv%d: latency: %02x\n",
+ bttv_num, latency));
+
+ btv->triton1=triton1 ? BT848_INT_ETBF : 0;
+ if (triton1 && btv->id >= 878)
+ {
+ triton1 = 0;
+ printk("bttv: Enabling 430FX compatibilty for bt878\n");
+ pcibios_read_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, &command);
+ command|=BT878_EN_TBFX;
+ pcibios_write_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, command);
+ pcibios_read_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, &command);
+ if (!(command&BT878_EN_TBFX))
+ {
+ printk("bttv: 430FX compatibility could not be enabled\n");
+ return -1;
+ }
+ }
+
+ bttv_num++;
+ }
+ if(bttv_num)
+ printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
+ return bttv_num;
+}
+#endif
X
X static void release_bttv(void)
X {
@@ -3048,10 +3674,17 @@
X i2c_unregister_bus((&btv->i2c));
X
X /* disable PCI bus-mastering */
+#if LINUX_VERSION_CODE >= 0x020100
X pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
X /* Should this be &=~ ?? */
- command|=PCI_COMMAND_MASTER;
+ command&=~PCI_COMMAND_MASTER;
X pci_write_config_byte(btv->dev, PCI_COMMAND, command);
+#else
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
+ command&=~PCI_COMMAND_MASTER;
+ pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
+
+#endif
X
X /* unmap and free memory */
X if (btv->grisc)
@@ -3081,7 +3714,7 @@
X video_unregister_device(&btv->video_dev);
X if(btv->vbi_dev.minor!=-1)
X video_unregister_device(&btv->vbi_dev);
- if (radio && btv->radio_dev.minor != -1)
+ if (radio[btv->nr] && btv->radio_dev.minor != -1)
X video_unregister_device(&btv->radio_dev);
X }
X }
@@ -3109,6 +3742,7 @@
X return -EIO;
X }
X }
+
X return 0;
X }
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.2.0-pre7/linux/drivers/char/bttv.h Thu Nov 12 16:21:18 1998
+++ linux/drivers/char/bttv.h Thu Jan 14 22:53:02 1999
@@ -21,7 +21,7 @@
X #ifndef _BTTV_H_
X #define _BTTV_H_
X
-#define TEST_VBI
+#define BTTV_VERSION_CODE 0x000520
X
X #include <linux/types.h>
X #include <linux/wait.h>
@@ -31,8 +31,14 @@
X #include "bt848.h"
X #include <linux/videodev.h>
X
+#ifndef O_NONCAP
+#define O_NONCAP O_TRUNC
+#endif
+
X #define MAX_GBUFFERS 2
X #define RISCMEM_LEN (32744*2)
+#define VBI_MAXLINES 19
+#define VBIBUF_SIZE (2048*VBI_MAXLINES*2)
X
X /* maximum needed buffer size for extended VBI frame mode capturing */
X #define BTTV_MAX_FBUF 0x190000
@@ -56,11 +62,20 @@
X };
X
X struct bttv_pll_info {
- unsigned int pll_ifreq; /* PLL input frequency */
- unsigned int pll_ofreq; /* PLL output frequency */
- unsigned int pll_crystal; /* Crystal used for input */
- unsigned int pll_current; /* Current programmed ofrq*/
+ unsigned int pll_ifreq; /* PLL input frequency */
+ unsigned int pll_ofreq; /* PLL output frequency */
+ unsigned int pll_crystal; /* Crystal used for input */
+ unsigned int pll_current; /* Currently programmed ofreq */
+};
+
+/* Per-open data for handling multiple opens on one device */
+struct device_open
+{
+ int isopen;
+ int noncapturing;
+ struct bttv *dev;
X };
+#define MAX_OPENS 3
X
X struct bttv
X {
@@ -70,6 +85,10 @@
X struct video_picture picture; /* Current picture params */
X struct video_audio audio_dev; /* Current audio params */
X
+ int user;
+ int capuser;
+ struct device_open open_data[MAX_OPENS];
+
X struct i2c_bus i2c;
X int have_msp3400;
X int have_tuner;
@@ -78,9 +97,12 @@
X
X unsigned int nr;
X unsigned short id;
+#if LINUX_VERSION_CODE < 0x020100
X unsigned char bus; /* PCI bus the Bt848 is on */
X unsigned char devfn;
+#else
X struct pci_dev *dev;
+#endif
X unsigned char irq; /* IRQ used by Bt848 card */
X unsigned char revision;
X unsigned int bt848_adr; /* bus address of IO mem returned by PCI BIOS */
@@ -92,7 +114,6 @@
X struct bttv_window win;
X int type; /* card type */
X int audio; /* audio mode */
- int user;
X int audio_chip;
X int radio;
X
@@ -115,7 +136,7 @@
X struct gbuffer *ogbuffers;
X struct gbuffer *egbuffers;
X u16 gwidth, gheight, gfmt;
- u16 gwidth_next, gheight_next, gfmt_next;
+ u16 gwidth_next, gheight_next, gfmt_next;
X u32 *grisc;
X
X unsigned long gro;
@@ -143,7 +164,6 @@
X int i2c_command;
X int triton1;
X };
-
X #endif
X
X /*The following should be done in more portable way. It depends on define
@@ -165,12 +185,11 @@
X
X #define BTTV_READEE _IOW('v', BASE_VIDIOCPRIVATE+0, char [256])
X #define BTTV_WRITEE _IOR('v', BASE_VIDIOCPRIVATE+1, char [256])
-#define BTTV_GRAB _IOR('v' , BASE_VIDIOCPRIVATE+2, struct gbuf)
X #define BTTV_FIELDNR _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)
X #define BTTV_PLLSET _IOW('v' , BASE_VIDIOCPRIVATE+3, struct bttv_pll_info)
-#define BTTV_BURST_ON _IOR('v' , BASE_VIDIOCPRIVATE+4, int)
-#define BTTV_BURST_OFF _IOR('v' , BASE_VIDIOCPRIVATE+5, int)
-#define BTTV_NAGRAVERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int)
+#define BTTV_BURST_ON _IOR('v' , BASE_VIDIOCPRIVATE+4, int)
+#define BTTV_BURST_OFF _IOR('v' , BASE_VIDIOCPRIVATE+5, int)
+#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int)
X #define BTTV_PICNR _IOR('v' , BASE_VIDIOCPRIVATE+7, int)
X
X
@@ -187,6 +206,7 @@
X #define BTTV_HAUPPAUGE878 0x0a
X #define BTTV_MIROPRO 0x0b
X #define BTTV_ADSTECH_TV 0x0c
+#define BTTV_AVERMEDIA98 0x0d
X
X #define AUDIO_TUNER 0x00
X #define AUDIO_RADIO 0x01
@@ -199,12 +219,19 @@
X
X #define TDA9850 0x01
X #define TDA8425 0x02
+#define TDA9840 0x03
X
X #define I2C_TSA5522 0xc2
+#define I2C_TDA9840 0x84
X #define I2C_TDA9850 0xb6
X #define I2C_TDA8425 0x82
X #define I2C_HAUPEE 0xa0
X #define I2C_STBEE 0xae


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 04'
echo 'File patch-2.2.0-pre8 is continued in part 05'
echo 05 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part05

#!/bin/sh
# this is part 05 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 05; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

+
+#define TDA9840_SW 0x00
+#define TDA9840_LVADJ 0x02
+#define TDA9840_STADJ 0x03
+#define TDA9840_TEST 0x04
X
X #define TDA9850_CON1 0x04
X #define TDA9850_CON2 0x05
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/hfmodem/main.c linux/drivers/char/hfmodem/main.c
--- v2.2.0-pre7/linux/drivers/char/hfmodem/main.c Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/hfmodem/main.c Sun Jan 17 18:28:06 1999
@@ -601,7 +601,7 @@
X MODULE_PARM(serio, "i");
X MODULE_PARM_DESC(serio, "address of serial port to output PTT");
X MODULE_PARM(pario, "i");
-MODULE_PARM_DESC(pario, "address of parial port to output PTT");
+MODULE_PARM_DESC(pario, "address of parallel port to output PTT");
X MODULE_PARM(midiio, "i");
X MODULE_PARM_DESC(midiio, "address of midi (MPU401) port to output PTT");
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/i2c.c linux/drivers/char/i2c.c
--- v2.2.0-pre7/linux/drivers/char/i2c.c Fri Oct 9 13:27:08 1998
+++ linux/drivers/char/i2c.c Thu Jan 14 22:53:02 1999
@@ -24,9 +24,11 @@
X static int verbose = 0;
X static int i2c_debug = 0;


X
+#if LINUX_VERSION_CODE >= 0x020117

X MODULE_PARM(scan,"i");
X MODULE_PARM(verbose,"i");
X MODULE_PARM(i2c_debug,"i");
+#endif


X
X /* ----------------------------------------------------------------------- */

X
@@ -34,8 +36,10 @@
X static struct i2c_driver *drivers[I2C_DRIVER_MAX];
X static int bus_count = 0, driver_count = 0;
X
+#ifdef CONFIG_VIDEO_BT848
X extern int i2c_tuner_init(void);
X extern int msp3400c_init(void);
+#endif
X
X int i2c_init(void)
X {
@@ -53,10 +57,10 @@
X
X static void i2c_attach_device(struct i2c_bus *bus, struct i2c_driver *driver)
X {
- unsigned long flags;
X struct i2c_device *device;
X int i,j,ack=1;
X unsigned char addr;
+ LOCK_FLAGS;
X
X /* probe for device */
X LOCK_I2C_BUS(bus);
@@ -148,8 +152,8 @@
X
X int i2c_register_bus(struct i2c_bus *bus)
X {
- unsigned long flags;
X int i,ack;
+ LOCK_FLAGS;
X
X memset(bus->devices,0,sizeof(bus->devices));
X bus->devcount = 0;
@@ -410,6 +414,7 @@
X
X #ifdef MODULE


X
+#if LINUX_VERSION_CODE >= 0x020100

X EXPORT_SYMBOL(i2c_register_bus);
X EXPORT_SYMBOL(i2c_unregister_bus);
X EXPORT_SYMBOL(i2c_register_driver);
@@ -424,7 +429,7 @@
X EXPORT_SYMBOL(i2c_readbyte);
X EXPORT_SYMBOL(i2c_read);
X EXPORT_SYMBOL(i2c_write);
-
+#endif
X
X int init_module(void)
X {
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
--- v2.2.0-pre7/linux/drivers/char/lp_m68k.c Wed Jan 13 15:00:41 1999
+++ linux/drivers/char/lp_m68k.c Fri Jan 15 17:46:27 1999
@@ -43,9 +43,7 @@
X #include <linux/string.h>
X #include <linux/timer.h>
X #include <linux/init.h>
-#ifdef CONFIG_KMOD
X #include <linux/kmod.h>
-#endif
X
X #ifdef CONFIG_AMIGA
X #ifdef CONFIG_MULTIFACE_III_LP
@@ -374,14 +372,12 @@
X if (dev >= MAX_LP)
X goto out_err;
X
-#ifdef CONFIG_KMOD
X if (!lp_table[dev]) {
X char modname[30];
X
X sprintf(modname, "char-major-%d-%d", LP_MAJOR, dev);
X request_module(modname);
X }
-#endif
X if (!lp_table[dev])
X goto out_err;
X if (!(lp_table[dev]->flags & LP_EXIST))
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.2.0-pre7/linux/drivers/char/misc.c Mon Jan 4 15:08:17 1999
+++ linux/drivers/char/misc.c Fri Jan 15 17:46:27 1999
@@ -49,9 +49,7 @@
X
X #include <linux/tty.h>
X #include <linux/selection.h>
-#ifdef CONFIG_KMOD
X #include <linux/kmod.h>
-#endif
X
X /*
X * Head entry for the doubly linked miscdevice list
@@ -108,7 +106,6 @@
X while ((c != &misc_list) && (c->minor != minor))
X c = c->next;
X if (c == &misc_list) {
-#ifdef CONFIG_KMOD
X char modname[20];
X sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor);
X request_module(modname);
@@ -116,7 +113,6 @@
X while ((c != &misc_list) && (c->minor != minor))
X c = c->next;
X if (c == &misc_list)
-#endif
X return -ENODEV;
X }
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c
--- v2.2.0-pre7/linux/drivers/char/msp3400.c Sun Nov 8 14:02:55 1998
+++ linux/drivers/char/msp3400.c Sun Jan 17 18:28:06 1999
@@ -1,21 +1,21 @@
X /*
X * programming the msp34* sound processor family
X *
- * (c) 1997,1998 Gerd Knorr <kra...@cs.tu-berlin.de>
+ * (c) 1997,1998 Gerd Knorr <kra...@goldbach.in-berlin.de>
X *
X * what works and what doesn't:
X *
- * AM mono
+ * AM-Mono
X * probably doesn't (untested)
X *
- * FM-mono
- * should work. FM stereo modes are backward-compatible to mono.
- * Therefore FM mono should always be available.
+ * FM-Mono
+ * should work. The stereo modes are backward compatible to FM-mono,
+ * therefore FM-Mono should be allways available.
X *
- * FM stereo (B/G, used in Germany)
+ * FM-Stereo (B/G, used in germany)
X * should work, with autodetect
X *
- * FM stereo (satellite)
+ * FM-Stereo (satellite)
X * should work, no autodetect (i.e. default is mono, but you can
X * switch to stereo -- untested)
X *
@@ -27,9 +27,14 @@
X * TODO:
X * - better SAT support
X *
+ *
+ * 980623 Thomas Sailer (sai...@ife.ee.ethz.ch)
+ * using soundcore instead of OSS
+ *


X */
X
X #include <linux/module.h>
+#include <linux/version.h>

X #include <linux/kernel.h>
X #include <linux/sched.h>
X #include <linux/string.h>
@@ -37,6 +42,10 @@


X #include <linux/delay.h>
X #include <linux/errno.h>

X #include <linux/malloc.h>
+#ifdef __SMP__
+#include <asm/pgtable.h>
+#include <linux/smp_lock.h>
+#endif
X
X /* kernel_thread */
X #define __KERNEL_SYSCALLS__
@@ -67,9 +76,9 @@
X int mode;
X int norm;
X int stereo;
+ int main, second; /* sound carrier */
X
- int mixer;
- int left, right; /* volume */
+ int left, right; /* volume */
X int bass, treble;
X
X /* thread */
@@ -88,7 +97,22 @@
X
X #define dprintk if (debug) printk
X
+#if LINUX_VERSION_CODE < 0x020100
+/* 2.0.x */


+#define signal_pending(current) (current->signal & ~current->blocked)
+#define sigfillset(set)

+#define mdelay(x) udelay(1000*x)
+#else
X MODULE_PARM(debug,"i");
+#endif
+
+#if LINUX_VERSION_CODE < 0x02017f
+void schedule_timeout(int j)
+{
+ current->timeout = jiffies + j;
+ schedule();
+}
+#endif
X
X /* ---------------------------------------------------------------------- */
X
@@ -211,9 +235,9 @@
X /* FM Radio */
X { { -8, -8, 4, 6, 78, 107 }, { -8, -8, 4, 6, 78, 107 },
X MSP_CARRIER(10.7), MSP_CARRIER(10.7),
- 0x00d0, 0x0480, 0x0020, 0x3002 },
+ 0x00d0, 0x0480, 0x0020, 0x3000 },
X
- /* Terrestial FM-mono */
+ /* Terrestial FM-mono + FM-stereo */
X { { 3, 18, 27, 48, 66, 72 }, { 3, 18, 27, 48, 66, 72 },
X MSP_CARRIER(5.5), MSP_CARRIER(5.5),
X 0x00d0, 0x0480, 0x0030, 0x3000},
@@ -230,7 +254,7 @@
X
X /* NICAM I */
X { { 2, 4, -6, -4, 40, 94 }, { 3, 18, 27, 48, 66, 72 },
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ MSP_CARRIER(6.0), MSP_CARRIER(6.0),
X 0x00d0, 0x0040, 0x0120, 0x3000},
X };
X
@@ -244,7 +268,7 @@
X { MSP_CARRIER(4.5), "4.5 NTSC" },
X { MSP_CARRIER(5.5), "5.5 PAL B/G" },
X { MSP_CARRIER(6.0), "6.0 PAL I" },
- { MSP_CARRIER(6.5), "6.5 PAL SAT / SECAM" }
+ { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" }
X };
X
X static struct CARRIER_DETECT carrier_detect_55[] = {
@@ -255,6 +279,9 @@
X
X static struct CARRIER_DETECT carrier_detect_65[] = {
X /* PAL SAT / SECAM */
+ { MSP_CARRIER(5.85), "5.85 PAL D/K NICAM" },
+ { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
+ { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
X { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
X { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
X { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
@@ -270,6 +297,7 @@
X msp3400c_write(bus,I2C_MSP3400C_DEM, 0x009b, cdo1 >> 12);
X msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00a3, cdo2 & 0xfff);
X msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00ab, cdo2 >> 12);
+ msp3400c_write(bus,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
X }
X
X static void msp3400c_setvolume(struct i2c_bus *bus, int left, int right)
@@ -329,12 +357,14 @@
X msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005,
X msp_init_data[type].fir2[i]);
X
- msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */
+ msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */
X msp_init_data[type].mode_reg);
X
X msp3400c_setcarrier(msp->bus, msp_init_data[type].cdo1,
X msp_init_data[type].cdo2);
X
+ msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
+
X msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,
X msp_init_data[type].dfp_src);
X msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,
@@ -357,9 +387,9 @@
X /* switch demodulator */
X switch (msp->mode) {
X case MSP_MODE_FM_TERRA:
- dprintk("msp3400: B/G setstereo: %d\n",mode);
+ dprintk("msp3400: FM setstereo: %d\n",mode);
X msp->stereo = mode;
- msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.7421875),MSP_CARRIER(5.5));
+ msp3400c_setcarrier(msp->bus,msp->second,msp->main);
X switch (mode) {
X case VIDEO_SOUND_STEREO:
X msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e, 0x3001);
@@ -372,7 +402,7 @@
X }
X break;
X case MSP_MODE_FM_SAT:
- dprintk("msp3400: sat setstereo: %d\n",mode);
+ dprintk("msp3400: SAT setstereo: %d\n",mode);
X msp->stereo = mode;
X switch (mode) {
X case VIDEO_SOUND_MONO:
@@ -390,9 +420,10 @@
X }
X break;
X case MSP_MODE_FM_NICAM1:
- dprintk("msp3400: NICAM1 setstereo: %d\n",mode);
+ case MSP_MODE_FM_NICAM2:
+ dprintk("msp3400: NICAM setstereo: %d\n",mode);
X msp->stereo = mode;
- msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.85),MSP_CARRIER(5.5));
+ msp3400c_setcarrier(msp->bus,msp->second,msp->main);
X nicam=0x0100;
X break;
X default:
@@ -406,7 +437,9 @@
X msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0020|nicam);
X msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0020|nicam);
X msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0020|nicam);
+#if 0
X msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0005,0x4000);
+#endif
X break;
X case VIDEO_SOUND_MONO:
X case VIDEO_SOUND_LANG1:
@@ -422,6 +455,27 @@
X }
X }
X
+static void
+msp3400c_print_mode(struct msp3400c *msp)
+{
+ if (msp->main == msp->second) {
+ printk("msp3400: mono sound carrier: %d.%03d MHz\n",
+ msp->main/910000,(msp->main/910)%1000);
+ } else {
+ printk("msp3400: main sound carrier: %d.%03d MHz\n",
+ msp->main/910000,(msp->main/910)%1000);
+ }
+ if (msp->mode == MSP_MODE_FM_NICAM1 ||
+ msp->mode == MSP_MODE_FM_NICAM2)
+ printk("msp3400: NICAM carrier : %d.%03d MHz\n",
+ msp->second/910000,(msp->second/910)%1000);
+ if (msp->mode == MSP_MODE_FM_TERRA &&
+ msp->main != msp->second) {
+ printk("msp3400: FM-stereo carrier : %d.%03d MHz\n",
+ msp->second/910000,(msp->second/910)%1000);
+ }
+}
+
X /* ----------------------------------------------------------------------- */
X
X struct REGISTER_DUMP {
@@ -452,15 +506,17 @@
X
X static int msp3400c_thread(void *data)
X {
- unsigned long flags;
X struct msp3400c *msp = data;
X struct semaphore sem = MUTEX_LOCKED;
X
X struct CARRIER_DETECT *cd;
X int count, max1,max2,val1,val2, val,this;
X int newstereo;
+ LOCK_FLAGS;
X
- /* lock_kernel(); */
+#ifdef __SMP__
+ lock_kernel();
+#endif
X
X exit_mm(current);
X current->session = 1;
@@ -472,7 +528,9 @@
X msp->wait = &sem;
X msp->thread = current;
X
- /* unlock_kernel(); */
+#ifdef __SMP__
+ unlock_kernel();
+#endif
X
X dprintk("msp3400: thread: start\n");
X if(msp->notify != NULL)
@@ -481,9 +539,11 @@
X for (;;) {
X if (msp->rmmod)
X goto done;
- dprintk("msp3400: thread: sleep\n");
+ if (debug > 1)
+ printk("msp3400: thread: sleep\n");
X down_interruptible(&sem);
- dprintk("msp3400: thread: wakeup\n");
+ if (debug > 1)
+ printk("msp3400: thread: wakeup\n");
X if (msp->rmmod || signal_pending(current))
X goto done;
X
@@ -510,6 +570,7 @@
X }
X break;
X case MSP_MODE_FM_NICAM1:
+ case MSP_MODE_FM_NICAM2:
X val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23);
X switch ((val & 0x1e) >> 1) {
X case 0:
@@ -553,7 +614,7 @@
X msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
X UNLOCK_I2C_BUS(msp->bus);
X
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
X schedule_timeout(HZ/25);
X if (signal_pending(current))
X goto done;
@@ -587,7 +648,7 @@
X msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
X UNLOCK_I2C_BUS(msp->bus);
X
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
X schedule_timeout(HZ/25);
X if (signal_pending(current))
X goto done;
@@ -603,34 +664,56 @@
X dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name);
X }
X
- /* program the msp3400 according to the results */
+ /* programm the msp3400 according to the results */
+ msp->main = carrier_detect_main[max1].cdo;
X switch (max1) {
- case 0: /* 4.5 */
X case 1: /* 5.5 */
- msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
- msp3400c_setcarrier(msp->bus, carrier_detect_main[max1].cdo,
- carrier_detect_main[max1].cdo);
X if (max2 == 0) {
X /* B/G FM-stereo */
+ msp->second = carrier_detect_55[max2].cdo;
+ msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
X msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
X msp->watch_stereo = 1;
- }
- if (max2 == 1 && msp->nicam) {
+ } else if (max2 == 1 && msp->nicam) {
X /* B/G NICAM */
+ msp->second = carrier_detect_55[max2].cdo;
X msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
- /* msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01); */
- msp3400c_setcarrier(msp->bus, MSP_CARRIER(5.85),
- MSP_CARRIER(5.5));
+ msp3400c_setcarrier(msp->bus, msp->second, msp->main);
X msp->watch_stereo = 1;
+ } else {
+ goto no_second;
X }
X break;
X case 2: /* 6.0 */
+ /* PAL I NICAM */
+ msp->second = MSP_CARRIER(6.552);
+ msp3400c_setmode(msp, MSP_MODE_FM_NICAM2);
+ msp3400c_setcarrier(msp->bus, msp->second, msp->main);
+ msp->watch_stereo = 1;
+ break;
X case 3: /* 6.5 */
+ if (max2 == 1 || max2 == 2) {
+ /* D/K FM-stereo */
+ msp->second = carrier_detect_65[max2].cdo;
+ msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
+ msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
+ msp->watch_stereo = 1;
+ } else if (max2 == 0 && msp->nicam) {
+ /* D/K NICAM */
+ msp->second = carrier_detect_65[max2].cdo;
+ msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
+ msp3400c_setcarrier(msp->bus, msp->second, msp->main);
+ msp->watch_stereo = 1;
+ } else {
+ goto no_second;
+ }
+ break;
+ case 0: /* 4.5 */
X default:
+ no_second:
+ msp->second = carrier_detect_main[max1].cdo;
X msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
- msp3400c_setcarrier(msp->bus, carrier_detect_main[max1].cdo,
- carrier_detect_main[max1].cdo);
- msp3400c_setstereo(msp, VIDEO_SOUND_STEREO);
+ msp3400c_setcarrier(msp->bus, msp->second, msp->main);
X break;
X }
X
@@ -640,9 +723,13 @@
X
X if (msp->watch_stereo) {
X del_timer(&msp->wake_stereo);
- msp->wake_stereo.expires = jiffies + HZ;
+ msp->wake_stereo.expires = jiffies + 2*HZ;
X add_timer(&msp->wake_stereo);
X }
+
+ if (debug)
+ msp3400c_print_mode(msp);
+
X msp->active = 0;
X }
X
@@ -713,7 +800,8 @@
X
X /* wait 1 sec */
X current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ);
+ current->timeout = jiffies + HZ;
+ schedule();
X if (signal_pending(current))
X goto done;
X if (msp->restart) {
@@ -752,9 +840,14 @@
X
X #ifdef REGISTER_MIXER
X
+#include <linux/sound.h>
X #include <linux/soundcard.h>
-#include <../drivers/sound/sound_config.h>
-#include <../drivers/sound/dev_table.h>
+#include <asm/uaccess.h>
+
+static struct msp3400c *mspmix = NULL; /* ugly hack, should do something more sensible */
+static int mixer_num;
+static int mixer_modcnt = 0;
+static struct semaphore mixer_sem = MUTEX;
X
X static int mix_to_v4l(int i)
X {
@@ -787,16 +880,42 @@
X return (r << 8) | l;
X }
X
-static int msp3400c_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+static int
+msp3400c_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
X {
- struct msp3400c *msp = mixer_devs[dev]->devc;
- unsigned long flags;
X int ret,val = 0;
+ LOCK_FLAGS;
+
+ if (cmd == SOUND_MIXER_INFO) {
+ mixer_info info;
+ strncpy(info.id, "MSP3400", sizeof(info.id));
+ strncpy(info.name, "MSP 3400", sizeof(info.name));
+ info.modify_counter = mixer_modcnt;
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ if (cmd == SOUND_OLD_MIXER_INFO) {
+ _old_mixer_info info;
+ strncpy(info.id, "MSP3400", sizeof(info.id));
+ strncpy(info.name, "MSP 3400", sizeof(info.name));
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ if (cmd == OSS_GETVERSION)
+ return put_user(SOUND_VERSION, (int *)arg);
X
X if (_SIOC_DIR(cmd) & _SIOC_WRITE)
X if (get_user(val, (int *)arg))
X return -EFAULT;
X
+ down(&mixer_sem);
+ if (!mspmix) {
+ up(&mixer_sem);
+ return -ENODEV;
+ }
+
X switch (cmd) {
X case MIXER_READ(SOUND_MIXER_RECMASK):
X case MIXER_READ(SOUND_MIXER_CAPS):
@@ -813,91 +932,97 @@
X break;
X
X case MIXER_WRITE(SOUND_MIXER_VOLUME):
- msp->left = mix_to_v4l(val);
- msp->right = mix_to_v4l(val >> 8);
- LOCK_I2C_BUS(msp->bus);
- msp3400c_setvolume(msp->bus,msp->left,msp->right);
- UNLOCK_I2C_BUS(msp->bus);
+ mspmix->left = mix_to_v4l(val);
+ mspmix->right = mix_to_v4l(val >> 8);
+ LOCK_I2C_BUS(mspmix->bus);
+ msp3400c_setvolume(mspmix->bus,mspmix->left,mspmix->right);
+ UNLOCK_I2C_BUS(mspmix->bus);
+ mixer_modcnt++;
X /* fall */
X case MIXER_READ(SOUND_MIXER_VOLUME):
- ret = v4l_to_mix2(msp->left, msp->right);
+ ret = v4l_to_mix2(mspmix->left, mspmix->right);
X break;
X
X case MIXER_WRITE(SOUND_MIXER_BASS):
- msp->bass = mix_to_v4l(val);
- LOCK_I2C_BUS(msp->bus);
- msp3400c_setbass(msp->bus,msp->bass);
- UNLOCK_I2C_BUS(msp->bus);
+ mspmix->bass = mix_to_v4l(val);
+ LOCK_I2C_BUS(mspmix->bus);
+ msp3400c_setbass(mspmix->bus,mspmix->bass);
+ UNLOCK_I2C_BUS(mspmix->bus);
+ mixer_modcnt++;
X /* fall */
X case MIXER_READ(SOUND_MIXER_BASS):
- ret = v4l_to_mix(msp->bass);
+ ret = v4l_to_mix(mspmix->bass);
X break;
X
X case MIXER_WRITE(SOUND_MIXER_TREBLE):
- msp->treble = mix_to_v4l(val);
- LOCK_I2C_BUS(msp->bus);
- msp3400c_settreble(msp->bus,msp->treble);
- UNLOCK_I2C_BUS(msp->bus);
+ mspmix->treble = mix_to_v4l(val);
+ LOCK_I2C_BUS(mspmix->bus);
+ msp3400c_settreble(mspmix->bus,mspmix->treble);
+ UNLOCK_I2C_BUS(mspmix->bus);
+ mixer_modcnt++;
X /* fall */
X case MIXER_READ(SOUND_MIXER_TREBLE):
- ret = v4l_to_mix(msp->treble);
+ ret = v4l_to_mix(mspmix->treble);
X break;
X
X default:
+ up(&mixer_sem);
X return -EINVAL;
X }
+ up(&mixer_sem);
X if (put_user(ret, (int *)arg))


X return -EFAULT;
X return 0;
X }

X
-struct mixer_operations msp3400c_mixer = {
- "video4linux",
- "TV card sound (msp3400)",
- msp3400c_mixer_ioctl
-};
-
-static int msp3400c_mixer_init(struct msp3400c *msp)
+static int
+msp3400c_mixer_open(struct inode *inode, struct file *file)
X {
- int m;
-
- msp->mixer = m = sound_alloc_mixerdev();
- if (m == -1)
- return -1;
-
- mixer_devs[m] = (struct mixer_operations *)
- kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
- if (mixer_devs[m] == NULL) {
- printk(KERN_ERR "msp3400c: can't allocate memory\n");
- sound_unload_mixerdev(m);
- return -1;
- }
- memcpy(mixer_devs[m],&msp3400c_mixer,sizeof(struct mixer_operations));
- mixer_devs[m]->devc = msp;
- return 0;


+ MOD_INC_USE_COUNT;
+ return 0;
X }
X

-static int msp3400c_mixer_close(struct msp3400c *msp)
+static int
+msp3400c_mixer_release(struct inode *inode, struct file *file)
X {
- int m = msp->mixer;
-
- if (m != -1 ) {
- sound_unload_mixerdev(m);
- kfree(mixer_devs[m]);
- }
- return 0;
+ MOD_DEC_USE_COUNT;


+ return 0;
X }
X

+static loff_t
+msp3400c_mixer_llseek(struct file *file, loff_t offset, int origin)
+{
+ return -ESPIPE;
+}
+
+static /*const*/ struct file_operations msp3400c_mixer_fops = {
+ &msp3400c_mixer_llseek,
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ &msp3400c_mixer_ioctl,
+ NULL, /* mmap */
+ &msp3400c_mixer_open,
+ NULL,
+ &msp3400c_mixer_release,
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL, /* lock */
+};
+
X #endif


X
X /* ----------------------------------------------------------------------- */

X
X static int msp3400c_attach(struct i2c_device *device)
X {
- unsigned long flags;
X struct semaphore sem = MUTEX_LOCKED;
X struct msp3400c *msp;
X int rev1,rev2;
+ LOCK_FLAGS;
X
X device->data = msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL);
X if (NULL == msp)
@@ -913,17 +1038,24 @@
X if (-1 == msp3400c_reset(msp->bus)) {
X UNLOCK_I2C_BUS(msp->bus);
X kfree(msp);
- return -EIO;
+ dprintk("msp3400: no chip found\n");
+ return -1;
X }
X
+ rev1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1e);
+ rev2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1f);
+ if (0 == rev1 && 0 == rev2) {
+ UNLOCK_I2C_BUS(msp->bus);
+ kfree(msp);
+ printk("msp3400: error while reading chip version\n");


+ return -1;
+ }
+

X msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
X msp3400c_setvolume(msp->bus, msp->left, msp->right);
X msp3400c_setbass(msp->bus, msp->bass);
X msp3400c_settreble(msp->bus, msp->treble);
X
- rev1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1e);
- rev2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1f);
-
X #if 0
X /* this will turn on a 1kHz beep - might be useful for debugging... */
X msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0014, 0x1040);
@@ -932,7 +1064,7 @@
X
X sprintf(device->name,"MSP34%02d%c-%c%d",
X (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
- msp->nicam = (((rev2>>8)&0xff) == 10) ? 1 : 0;
+ msp->nicam = (((rev2>>8)&0xff) != 00) ? 1 : 0;
X
X /* timer for stereo checking */
X msp->wake_stereo.function = msp3400c_stereo_wake;
@@ -951,8 +1083,9 @@
X if (msp->nicam)
X printk(", has NICAM support");
X #ifdef REGISTER_MIXER
- if (0 == msp3400c_mixer_init(msp))
- printk(", registered as sound mixer");
+ down(&mixer_sem);
+ mspmix = msp;
+ up(&mixer_sem);
X #endif
X printk("\n");
X return 0;
@@ -960,12 +1093,14 @@
X
X static int msp3400c_detach(struct i2c_device *device)
X {
- unsigned long flags;
X struct semaphore sem = MUTEX_LOCKED;
X struct msp3400c *msp = (struct msp3400c*)device->data;
+ LOCK_FLAGS;
X
X #ifdef REGISTER_MIXER
- msp3400c_mixer_close(msp);
+ down(&mixer_sem);
+ mspmix = NULL;
+ up(&mixer_sem);
X #endif
X
X /* shutdown control thread */
@@ -992,9 +1127,10 @@
X static int msp3400c_command(struct i2c_device *device,
X unsigned int cmd, void *arg)
X {
- unsigned long flags;
X struct msp3400c *msp = (struct msp3400c*)device->data;
X int *iarg = (int*)arg;
+ __u16 *sarg = arg;
+ LOCK_FLAGS;
X
X switch (cmd) {
X case MSP_SET_RADIO:
@@ -1004,12 +1140,22 @@
X LOCK_I2C_BUS(msp->bus);
X msp3400c_setmode(msp,MSP_MODE_FM_RADIO);
X msp3400c_setcarrier(msp->bus, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
+ msp3400c_setvolume(msp->bus,msp->left, msp->right);
X UNLOCK_I2C_BUS(msp->bus);
X break;
X case MSP_SET_TVNORM:
X msp->norm = *iarg;
X break;
+ case MSP_SWITCH_MUTE:
+ /* channels switching step one -- mute */
+ msp->watch_stereo=0;
+ del_timer(&msp->wake_stereo);
+ LOCK_I2C_BUS(msp->bus);
+ msp3400c_setvolume(msp->bus,0,0);
+ UNLOCK_I2C_BUS(msp->bus);
+ break;
X case MSP_NEWCHANNEL:
+ /* channels switching step two -- trigger sound carrier scan */
X msp->watch_stereo=0;
X del_timer(&msp->wake_stereo);
X if (!msp->active)
@@ -1019,59 +1165,55 @@
X break;
X
X case MSP_GET_VOLUME:
- *iarg = (msp->left > msp->right) ? msp->left : msp->right;
+ *sarg = (msp->left > msp->right) ? msp->left : msp->right;
X break;
X case MSP_SET_VOLUME:
- msp->left = msp->right = *iarg;
+ msp->left = msp->right = *sarg;
X LOCK_I2C_BUS(msp->bus);
X msp3400c_setvolume(msp->bus,msp->left, msp->right);
X UNLOCK_I2C_BUS(msp->bus);
X break;
X
X case MSP_GET_BASS:
- *iarg = msp->bass;
+ *sarg = msp->bass;
X break;
X case MSP_SET_BASS:
- msp->bass = *iarg;
+ msp->bass = *sarg;
X LOCK_I2C_BUS(msp->bus);
X msp3400c_setbass(msp->bus,msp->bass);
X UNLOCK_I2C_BUS(msp->bus);
X break;
X
X case MSP_GET_TREBLE:
- *iarg = msp->treble;
+ *sarg = msp->treble;
X break;
X case MSP_SET_TREBLE:
- msp->treble = *iarg;
+ msp->treble = *sarg;
X LOCK_I2C_BUS(msp->bus);
X msp3400c_settreble(msp->bus,msp->treble);
X UNLOCK_I2C_BUS(msp->bus);
X break;
X
X case MSP_GET_STEREO:
- *iarg = msp->stereo;
+ *sarg = msp->stereo;
X break;
X case MSP_SET_STEREO:
- if (*iarg) {
+ if (*sarg) {
X msp->watch_stereo=0;
X del_timer(&msp->wake_stereo);
X LOCK_I2C_BUS(msp->bus);
- msp3400c_setstereo(msp,*iarg);
+ msp3400c_setstereo(msp,*sarg);
X UNLOCK_I2C_BUS(msp->bus);
X }
X break;
X
X case MSP_GET_DC:
X LOCK_I2C_BUS(msp->bus);
- *iarg = (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b) +
- (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c);
+ *sarg = ((int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b) +
+ (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c));
X UNLOCK_I2C_BUS(msp->bus);
X break;
-
- case MSP_GET_UNIT:
- *iarg = msp->mixer;
- break;
-
+
X default:
X return -EINVAL;
X }
@@ -1090,8 +1232,6 @@
X msp3400c_command
X };
X
-EXPORT_NO_SYMBOLS;
-
X #ifdef MODULE
X int init_module(void)
X #else
@@ -1099,6 +1239,10 @@
X #endif
X {
X i2c_register_driver(&i2c_driver_msp);
+#ifdef REGISTER_MIXER
+ if ((mixer_num = register_sound_mixer(&msp3400c_mixer_fops, -1)) < 0)
+ printk(KERN_ERR "msp3400c: cannot allocate mixer device\n");
+#endif


X return 0;
X }
X

@@ -1106,6 +1250,10 @@
X void cleanup_module(void)
X {
X i2c_unregister_driver(&i2c_driver_msp);
+#ifdef REGISTER_MIXER
+ if (mixer_num >= 0)
+ unregister_sound_mixer(mixer_num);
+#endif
X }
X #endif
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/msp3400.h linux/drivers/char/msp3400.h
--- v2.2.0-pre7/linux/drivers/char/msp3400.h Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/msp3400.h Thu Jan 14 22:53:02 1999
@@ -7,19 +7,19 @@
X #define MSP_SET_RADIO _IO('m',2) /* Radio mode */
X #define MSP_NEWCHANNEL _IO('m',3) /* indicate new channel */
X
-#define MSP_GET_VOLUME _IOR('m',4,int)
-#define MSP_SET_VOLUME _IOW('m',5,int)
+#define MSP_GET_VOLUME _IOR('m',4,__u16)
+#define MSP_SET_VOLUME _IOW('m',5,__u16)
X
-#define MSP_GET_STEREO _IOR('m',6,int)
-#define MSP_SET_STEREO _IOW('m',7,int)
+#define MSP_GET_STEREO _IOR('m',6,__u16)
+#define MSP_SET_STEREO _IOW('m',7,__u16)
X
-#define MSP_GET_DC _IOW('m',8,int)
+#define MSP_GET_DC _IOW('m',8,__u16)
X
-#define MSP_GET_BASS _IOR('m', 9,int)
-#define MSP_SET_BASS _IOW('m',10,int)
-#define MSP_GET_TREBLE _IOR('m',11,int)
-#define MSP_SET_TREBLE _IOW('m',12,int)
-
-#define MSP_GET_UNIT _IOR('m',13,int)
+#define MSP_GET_BASS _IOR('m', 9,__u16)
+#define MSP_SET_BASS _IOW('m',10,__u16)
+#define MSP_GET_TREBLE _IOR('m',11,__u16)
+#define MSP_SET_TREBLE _IOW('m',12,__u16)
X
+#define MSP_GET_UNIT _IOR('m',13,int)
+#define MSP_SWITCH_MUTE _IO('m',14)
X #endif /* MSP3400_H */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.2.0-pre7/linux/drivers/char/n_tty.c Fri Jan 8 22:36:05 1999
+++ linux/drivers/char/n_tty.c Sun Jan 17 10:39:27 1999
@@ -922,10 +922,10 @@
X }
X }
X
- add_wait_queue(&tty->read_wait, &wait);
-
X if (down_interruptible(&tty->atomic_read))
X return -ERESTARTSYS;
+
+ add_wait_queue(&tty->read_wait, &wait);
X set_bit(TTY_DONT_FLIP, &tty->flags);
X while (nr) {
X /* First test for status change. */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.2.0-pre7/linux/drivers/char/pc_keyb.c Wed Jan 13 15:00:41 1999
+++ linux/drivers/char/pc_keyb.c Fri Jan 15 11:28:55 1999
@@ -65,7 +65,7 @@
X static volatile unsigned char resend = 0;
X
X
-#if defined(CONFIG_PSMOUSE)
+#if defined CONFIG_PSMOUSE
X /*
X * PS/2 Auxiliary Device
X */
@@ -87,7 +87,7 @@
X #endif /* CONFIG_PSMOUSE */
X
X /*
- * Wait for keyboard controller input buffer is empty.
+ * Wait for keyboard controller input buffer to drain.
X *
X * Don't use 'jiffies' so that we don't depend on
X * interrupts..
@@ -709,6 +709,52 @@
X }
X
X #if defined CONFIG_PSMOUSE
+
+/*
+ * Check if this is a dual port controller.
+ */
+static int __init detect_auxiliary_port(void)
+{
+ unsigned long flags;
+ unsigned char status;
+ unsigned char val;
+ int loops = 5;
+ int retval = 0;
+
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+
+ /* Put the value 0x5A in the output buffer using the "Write
+ * Auxiliary Device Output Buffer" command (0xD3). Poll the
+ * Status Register for a while to see if the value really
+ * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
+ * bit is also set to 1 in the Status Register, we assume this
+ * controller has an Auxiliary Port (a.k.a. Mouse Port).
+ */
+ kb_wait();
+ outb(KBD_CCMD_WRITE_AUX_OBUF, KBD_CNTL_REG);
+
+ kb_wait();
+ outb(0x5a, KBD_DATA_REG); /* 0x5a is a random dummy value. */
+
+ status = inb(KBD_STATUS_REG);
+ while (!(status & KBD_STAT_OBF) && loops--) {
+ mdelay(1);
+ status = inb(KBD_STATUS_REG);
+ }
+
+ if (status & KBD_STAT_OBF) {
+ val = inb(KBD_DATA_REG);
+ if (val == 0x5a && (status & KBD_STAT_MOUSE_OBF)) {
+ printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
+ retval = 1;
+ }
+ }
+
+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
+
+ return retval;
+}
+
X /*
X * Send a byte to the mouse.
X */
@@ -894,18 +940,9 @@
X
X static int __init psaux_init(void)
X {
-#if 0
- /*
- * Don't bother with the BIOS flag: even if we don't have
- * a mouse connected at bootup we may still want to connect
- * one later, and we don't want to just let the BIOS tell
- * us that it has no mouse..
- */
- if (aux_device_present != 0xaa)
+ if (!detect_auxiliary_port())
X return -EIO;
X
- printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n");
-#endif
X misc_register(&psaux_mouse);
X queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
X memset(queue, 0, sizeof(*queue));
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/pc_keyb.h linux/drivers/char/pc_keyb.h
--- v2.2.0-pre7/linux/drivers/char/pc_keyb.h Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/pc_keyb.h Thu Jan 14 10:39:09 1999
@@ -51,6 +51,8 @@
X #define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
X #define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
X #define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
+ initiated by the auxiliary device */
X #define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
X
X /*
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.2.0-pre7/linux/drivers/char/pcxx.c Sun Nov 8 14:02:55 1998
+++ linux/drivers/char/pcxx.c Sun Jan 17 18:28:06 1999
@@ -70,6 +70,7 @@
X #include <linux/malloc.h>
X #include <linux/string.h>
X #include <linux/init.h>
+#include <linux/version.h>
X
X #ifndef MODULE
X #include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.2.0-pre7/linux/drivers/char/rtc.c Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/rtc.c Thu Jan 14 22:58:47 1999
@@ -93,7 +93,7 @@
X static inline unsigned char rtc_is_updating(void);
X
X /*
- * Bits in rtc_status. (7 bits of room for future expansion)
+ * Bits in rtc_status. (6 bits of room for future expansion)
X */
X
X #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/saa5249.c linux/drivers/char/saa5249.c
--- v2.2.0-pre7/linux/drivers/char/saa5249.c Thu Nov 12 16:21:19 1998
+++ linux/drivers/char/saa5249.c Thu Jan 14 22:53:02 1999


@@ -460,7 +460,7 @@
X

X if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */
X (memcmp(infobits, t->vdau[req.pgbuf].laststat, sizeof(infobits)) ||
- jiffies >= t->vdau[req.pgbuf].expire))
+ time_after_eq(jiffies, t->vdau[req.pgbuf].expire)))
X { /* check if new page arrived */
X if (i2c_senddata(t, CCTWR, 8, 0, 0, 0, -1) ||
X i2c_getdata(t, CCTRD, VTX_PAGESIZE, t->vdau[req.pgbuf].pgbuf, FALSE))
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.2.0-pre7/linux/drivers/char/serial.c Thu Jan 7 15:11:36 1999
+++ linux/drivers/char/serial.c Thu Jan 14 10:27:53 1999
@@ -1681,7 +1681,7 @@
X new_serial.irq = irq_cannonicalize(new_serial.irq);
X
X if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
- (new_serial.baud_base == 0) || (new_serial.type < PORT_UNKNOWN) ||
+ (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) ||
X (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) ||
X (new_serial.type == PORT_STARTECH)) {
X return -EINVAL;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.2.0-pre7/linux/drivers/char/tty_io.c Fri Jan 8 22:36:05 1999
+++ linux/drivers/char/tty_io.c Fri Jan 15 17:46:27 1999
@@ -89,9 +89,7 @@
X #include <linux/vt_kern.h>
X #include <linux/selection.h>
X
-#ifdef CONFIG_KMOD
X #include <linux/kmod.h>
-#endif
X
X #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
X #define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
@@ -219,7 +217,6 @@
X
X if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
X return -EINVAL;
-#ifdef CONFIG_KMOD
X /* Eduardo Blanco <ej...@cs.cs.com.uy> */
X /* Cyrus Durgin <ci...@speakeasy.org> */
X if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
@@ -227,7 +224,6 @@
X sprintf(modname, "tty-ldisc-%d", ldisc);
X request_module (modname);
X }
-#endif
X if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
X return -EINVAL;
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/tuner.c linux/drivers/char/tuner.c
--- v2.2.0-pre7/linux/drivers/char/tuner.c Thu Nov 12 16:21:19 1998
+++ linux/drivers/char/tuner.c Sun Jan 17 18:28:06 1999
@@ -6,19 +6,31 @@


X #include <linux/delay.h>
X #include <linux/errno.h>

X #include <linux/malloc.h>
+#include <linux/version.h>
X
X #include <linux/i2c.h>
X #include <linux/videodev.h>
X
X #include "tuner.h"
X
-static int debug = 0; /* insmod parameter */
-static int type = 0; /* tuner type */
+static int debug = 0; /* insmod parameter */
+static int type = -1; /* tuner type */
X
X #define dprintk if (debug) printk
X
+#if LINUX_VERSION_CODE > 0x020100
X MODULE_PARM(debug,"i");
X MODULE_PARM(type,"i");
+#endif
+
+#if LINUX_VERSION_CODE < 0x02017f
+void schedule_timeout(int j)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + j;
+ schedule();
+}
+#endif
X
X struct tuner
X {
@@ -69,9 +81,10 @@
X {"Temic NTSC", TEMIC, NTSC,
X 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2,732},
X {"TEMIC PAL_I", TEMIC, PAL_I,
- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
+ // 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
+ 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,0xc2,623},
X {"Temic 4036 FY5 NTSC", TEMIC, NTSC,
- 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
+ 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
X };
X
X /* ---------------------------------------------------------------------- */
@@ -98,11 +111,17 @@
X
X static void set_tv_freq(struct tuner *t, int freq)
X {
- unsigned long flags;
X u8 config;
X u16 div;
- struct tunertype *tun=&tuners[t->type];
+ struct tunertype *tun;
+ LOCK_FLAGS;
X
+ if (t->type == -1) {
+ printk("tuner: tuner type not set\n");
+ return;
+ }
+
+ tun=&tuners[t->type];
X if (freq < tun->thresh1)
X config = tun->VHF_L;
X else if (freq < tun->thresh2)
@@ -125,11 +144,17 @@
X
X static void set_radio_freq(struct tuner *t, int freq)
X {
- unsigned long flags;
X u8 config;
X u16 div;
- struct tunertype *tun=&tuners[type];
+ struct tunertype *tun;
+ LOCK_FLAGS;
+
+ if (t->type == -1) {
+ printk("tuner: tuner type not set\n");
+ return;
+ }
X
+ tun=&tuners[t->type];
X config = 0xa5;
X div=freq + (int)(16*10.7);
X div&=0x7fff;
@@ -143,7 +168,7 @@
X }
X if (debug) {
X UNLOCK_I2C_BUS(t->bus);
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
X schedule_timeout(HZ/10);
X LOCK_I2C_BUS(t->bus);
X
@@ -181,7 +206,8 @@
X t->bus = device->bus;
X t->addr = device->addr;
X t->type = type;
- dprintk("tuner: type is %d (%s)\n",t->type,tuners[t->type].name);
+ dprintk("tuner: type is %d (%s)\n",t->type,
+ (t->type == -1 ) ? "autodetect" : tuners[t->type].name);
X
X MOD_INC_USE_COUNT;
X return 0;
@@ -204,6 +230,8 @@
X switch (cmd)
X {
X case TUNER_SET_TYPE:
+ if (t->type != -1)
+ return 0;
X t->type = *iarg;
X dprintk("tuner: type set to %d (%s)\n",
X t->type,tuners[t->type].name);
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.2.0-pre7/linux/drivers/char/videodev.c Mon Dec 28 15:00:52 1998
+++ linux/drivers/char/videodev.c Fri Jan 15 17:46:27 1999
@@ -24,12 +24,12 @@
X #include <linux/errno.h>
X #include <linux/videodev.h>


X
+#if LINUX_VERSION_CODE >= 0x020100

X #include <asm/uaccess.h>
+#endif
X #include <asm/system.h>
X
-#ifdef CONFIG_KMOD
X #include <linux/kmod.h>
-#endif
X
X
X #define VIDEO_NUM_DEVICES 256
@@ -103,17 +103,17 @@
X #endif
X #ifdef CONFIG_RADIO_SF16FMI
X {"SF16FMI", fmi_init},
-#endif
+#endif
X #ifdef CONFIG_RADIO_MIROPCM20
X {"PCM20", pcm20_init},
-#endif
+#endif
X #ifdef CONFIG_RADIO_GEMTEK
- {"GemTek", gemtek_init},
-#endif
+ {"GemTek", gemtek_init},
+#endif
X {"end", NULL}
X };
X
-
+#if LINUX_VERSION_CODE >= 0x020100
X /*
X * Read will do some smarts later on. Buffer pin etc.
X */
@@ -129,6 +129,7 @@
X }
X
X
+
X /*
X * Write for now does nothing. No reason it shouldnt do overlay setting
X * for some boards I guess..
@@ -144,7 +145,6 @@


X return 0;
X }
X

-
X /*
X * Poll to see if we're readable, can probably be used for timing on incoming
X * frames, etc..
@@ -159,6 +159,32 @@


X return 0;
X }
X
+

+#else
+static int video_read(struct inode *ino,struct file *file,
+ char *buf, int count)
+{
+ int err;
+ struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
+ if (vfl->read)
+ return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
+ else


+ return -EINVAL;
+}
+

+static int video_write(struct inode *ino,struct file *file, const char *buf,
+ int count)
+{
+ int err;
+ struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
+ if (vfl->write)
+ return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
+ else


+ return 0;
+}
+

+#endif
+
X /*
X * Open a video device.
X */
@@ -174,14 +200,12 @@
X
X vfl=video_device[minor];
X if(vfl==NULL) {
-#ifdef CONFIG_KMOD
X char modname[20];
X
X sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor);
X request_module(modname);
X vfl=video_device[minor];
X if (vfl==NULL)
-#endif
X return -ENODEV;
X }
X if(vfl->busy)
@@ -218,11 +242,19 @@
X * image ?


X */
X
+#if LINUX_VERSION_CODE >= 0x020100

X static long long video_lseek(struct file * file,
X long long offset, int origin)
X {
X return -ESPIPE;
X }
+#else
+static long long video_lseek(struct inode *inode, struct file * file,
+ long long offset, int origin)
+{
+ return -ESPIPE;
+}
+#endif
X
X
X static int video_ioctl(struct inode *inode, struct file *file,
@@ -246,9 +278,16 @@
X */


X
X
+#if LINUX_VERSION_CODE >= 0x020100

X int video_mmap(struct file *file, struct vm_area_struct *vma)
X {
X struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+#else
+static int video_mmap(struct inode * ino, struct file * file,
+ struct vm_area_struct * vma)
+{
+ struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
+#endif
X if(vfl->mmap)
X return vfl->mmap(vfl, (char *)vma->vm_start,
X (unsigned long)(vma->vm_end-vma->vm_start));
@@ -332,11 +371,17 @@
X video_read,
X video_write,
X NULL, /* readdir */
+#if LINUX_VERSION_CODE >= 0x020100
X video_poll, /* poll */
+#else
+ NULL,
+#endif
X video_ioctl,
X video_mmap,
X video_open,
+#if LINUX_VERSION_CODE >= 0x020100
X NULL, /* flush */
+#endif
X video_release
X };
X
@@ -380,5 +425,7 @@
X
X #endif


X
+#if LINUX_VERSION_CODE >= 0x020100

X EXPORT_SYMBOL(video_register_device);
X EXPORT_SYMBOL(video_unregister_device);
+#endif
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/3c523.c linux/drivers/net/3c523.c
--- v2.2.0-pre7/linux/drivers/net/3c523.c Fri Jan 8 22:36:06 1999
+++ linux/drivers/net/3c523.c Sun Jan 17 18:28:06 1999
@@ -184,7 +184,7 @@
X
X /* helper-functions */
X static int init586(struct device *dev);
-static int check586(struct device *dev, char *where, unsigned size);
+static int check586(struct device *dev, unsigned long where, unsigned size);
X static void alloc586(struct device *dev);
X static void startrecv586(struct device *dev);
X static void *alloc_rfa(struct device *dev, void *ptr);
@@ -311,19 +311,19 @@
X * Check to see if there's an 82586 out there.
X */
X
-__initfunc(static int check586(struct device *dev, char *where, unsigned size))
+__initfunc(static int check586(struct device *dev, unsigned long where, unsigned size))
X {
X struct priv *p = (struct priv *) dev->priv;
X char *iscp_addrs[2];
X int i = 0;
X
- p->base = (unsigned long) where + size - 0x01000000;
- p->memtop = where + size;
- p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
+ p->base = where + size - 0x01000000;
+ p->memtop = phys_to_virt(where) + size;
+ p->scp = (struct scp_struct *)phys_to_virt(p->base + SCP_DEFAULT_ADDRESS);
X memset((char *) p->scp, 0, sizeof(struct scp_struct));
X p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */
X
- iscp_addrs[0] = where;
+ iscp_addrs[0] = phys_to_virt(where);
X iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
X
X for (i = 0; i < 2; i++) {
@@ -358,7 +358,7 @@
X elmc_id_reset586();
X DELAY(2);
X
- p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
+ p->scp = (struct scp_struct *) phys_to_virt(p->base + SCP_DEFAULT_ADDRESS);
X p->scb = (struct scb_struct *) phys_to_virt(dev->mem_start);
X p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
X
@@ -531,7 +531,7 @@
X elmc_id_reset586(); /* seems like a good idea before checking it... */
X
X size = 0x4000; /* check for 16K mem */
- if (!check586(dev, (char *) phys_to_virt(dev->mem_start), size)) {
+ if (!check586(dev, dev->mem_start, size)) {
X printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
X dev->mem_start);
X release_region(dev->base_addr, ELMC_IO_EXTENT);
@@ -539,7 +539,7 @@
X }
X dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */
X
- ((struct priv *) (dev->priv))->base = (unsigned long)phys_to_virt(dev->mem_start + size - 0x01000000);
+ ((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000;
X alloc586(dev);
X
X elmc_id_reset586(); /* make sure it doesn't generate spurious ints */
@@ -963,7 +963,7 @@
X if (skb != NULL) {
X skb->dev = dev;
X skb_reserve(skb, 2); /* 16 byte alignment */
- memcpy(skb_put(skb, totlen), (char *) p->base + (unsigned long) rbd->buffer, totlen);
+ memcpy(skb_put(skb, totlen), (u8 *)phys_to_virt(p->base) + (unsigned long) rbd->buffer, totlen);
X skb->protocol = eth_type_trans(skb, dev);
X netif_rx(skb);
X p->stats.rx_packets++;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.2.0-pre7/linux/drivers/net/3c59x.c Wed Jan 13 15:00:42 1999
+++ linux/drivers/net/3c59x.c Thu Jan 14 22:58:47 1999
@@ -1489,6 +1489,7 @@
X outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
X }
X }
+ vp->stats.tx_bytes += skb->len;


X return 0;
X }
X

@@ -1548,6 +1549,7 @@
X clear_bit(0, (void*)&dev->tbusy);
X }
X dev->trans_start = jiffies;
+ vp->stats.tx_bytes += skb->len;


X return 0;
X }
X }

@@ -1732,6 +1734,7 @@
X netif_rx(skb);
X dev->last_rx = jiffies;
X vp->stats.rx_packets++;
+ vp->stats.rx_bytes += skb->len;
X /* Wait a limited time to go to next packet. */
X for (i = 200; i >= 0; i--)
X if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
@@ -1783,6 +1786,7 @@
X int pkt_len = rx_status & 0x1fff;
X struct sk_buff *skb;
X
+ vp->stats.rx_bytes += pkt_len;
X if (vortex_debug > 4)
X printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
X pkt_len, rx_status);
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.2.0-pre7/linux/drivers/net/Config.in Mon Dec 28 15:00:52 1998
+++ linux/drivers/net/Config.in Sun Jan 17 18:28:06 1999
@@ -59,7 +59,7 @@
X tristate '3c515 ISA Fast EtherLink' CONFIG_3C515
X tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
X fi
- bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE
+ tristate 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE
X bool 'Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC
X if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then
X tristate 'WD80*3 support' CONFIG_WD80x3
@@ -227,6 +227,7 @@
X # The COSA/SRP driver has not been tested as non-modular yet.
X #
X dep_tristate 'COSA/SRP sync serial boards support' CONFIG_COSA m
+tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI
X #
X if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
X bool 'WAN drivers' CONFIG_WAN_DRIVERS
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.2.0-pre7/linux/drivers/net/Makefile Fri Jan 8 22:36:06 1999
+++ linux/drivers/net/Makefile Thu Jan 14 22:58:47 1999
@@ -1060,5 +1060,5 @@
X wanpipe.o: $(WANPIPE_OBJS)
X ld -r -o $@ $(WANPIPE_OBJS)
X
-rcpci.o: rcpci45.o rcmtl.o
- $(LD) -r -o rcpci.o rcpci45.o rcmtl.o
+rcpci.o: rcpci45.o rclanmtl.o
+ $(LD) -r -o rcpci.o rcpci45.o rclanmtl.o
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.2.0-pre7/linux/drivers/net/Space.c Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/Space.c Fri Jan 15 14:36:21 1999
@@ -128,7 +128,6 @@
X extern int apfddi_init(struct device *dev);
X
X /* HIPPI boards */
-extern int cern_hippi_probe(struct device *);
X extern int rr_hippi_probe(struct device *);
X
X struct devprobe
@@ -177,9 +176,6 @@
X #ifdef CONFIG_VORTEX
X {tc59x_probe, 0},
X #endif
-#ifdef CONFIG_DEC_ELCP
- {tulip_probe, 0},
-#endif
X #ifdef CONFIG_NE2K_PCI
X {ne2k_pci_probe, 0},
X #endif
@@ -189,6 +185,9 @@
X #ifdef CONFIG_EEXPRESS_PRO100 /* Intel EtherExpress Pro/100 */
X {eepro100_probe, 0},
X #endif
+#ifdef CONFIG_DEC_ELCP
+ {tulip_probe, 0},
+#endif
X #ifdef CONFIG_DE4X5 /* DEC DE425, DE434, DE435 adapters */
X {de4x5_probe, 0},
X #endif
@@ -541,9 +540,6 @@
X return 1;
X
X if (1
-#ifdef CONFIG_CERN_HIPPI
- && cern_hippi_probe(dev)
-#endif
X #ifdef CONFIG_ROADRUNNER
X && rr_hippi_probe(dev)
X #endif
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.2.0-pre7/linux/drivers/net/acenic.c Fri Jan 8 22:36:06 1999
+++ linux/drivers/net/acenic.c Sun Jan 17 18:28:06 1999
@@ -121,7 +121,6 @@
X * TODO:
X *
X * - Add multicast support.
- * - The Tigon II firmware fails to run in some PCs.
X * - NIC dump support.
X * - More tuning parameters.
X */
@@ -133,15 +132,16 @@
X static int max_tx_desc[8] = {0, };
X static int max_rx_desc[8] = {0, };
X
-static const char *version = "acenic.c: v0.22 01/07/99 Jes Sorensen (Jes.So...@cern.ch)\n";
+static const char *version = "acenic.c: v0.24 01/13/99 Jes Sorensen (Jes.So...@cern.ch)\n";
X
X static struct device *root_dev = NULL;
X
X static int ace_load_firmware(struct device *dev);
X
+static int probed __initdata = 0;
+
X __initfunc(int acenic_probe (struct device *dev))
X {
- static int i = 0;
X int boards_found = 0;
X int version_disp;
X struct ace_private *ap;
@@ -154,6 +154,10 @@
X #endif
X struct pci_dev *pdev = NULL;
X
+ if (probed)
+ return -ENODEV;
+ probed ++;
+
X if (!pci_present()) /* is PCI support present? */
X return -ENODEV;
X
@@ -183,8 +187,6 @@
X ap->pdev = pdev;
X ap->vendor = pdev->vendor;
X
- pci_set_master(pdev);
-
X dev->irq = pdev->irq;
X #ifdef __SMP__
X spin_lock_init(&ap->lock);
@@ -221,6 +223,8 @@
X pci_latency);
X }
X
+ pci_set_master(pdev);
+
X switch(ap->vendor){
X case PCI_VENDOR_ID_ALTEON:
X sprintf(ap->name, "AceNIC Gigabit Ethernet");
@@ -246,7 +250,8 @@
X 0x4000);
X if (!ap->regs){
X printk(KERN_ERR "%s: Unable to map I/O register, "
- "AceNIC %i will be disabled.\n", dev->name, i);
+ "AceNIC %i will be disabled.\n",
+ dev->name, boards_found);
X break;
X }
X
@@ -401,13 +406,6 @@
X ((CLR_INT | WORD_SWAP) << 24));
X #endif
X
-#ifdef __LITTLE_ENDIAN
- regs->ModeStat = ACE_BYTE_SWAP_DATA | ACE_WARN | ACE_FATAL
- | ACE_WORD_SWAP;
-#else
-#error "this driver doesn't run on big-endian machines yet!"
-#endif
-
X /*
X * Stop the NIC CPU and clear pending interrupts
X */
@@ -438,6 +436,20 @@
X tig_ver);
X return -ENODEV;
X }
+
+ /*
+ * ModeStat _must_ be set after the SRAM settings as this change
+ * seems to corrupt the ModeStat and possible other registers.
+ * The SRAM settings survive resets and setting it to the same
+ * value a second time works as well. This is what caused the
+ * `Firmware not running' problem on the Tigon II.
+ */
+#ifdef __LITTLE_ENDIAN
+ regs->ModeStat = ACE_BYTE_SWAP_DATA | ACE_WARN | ACE_FATAL
+ | ACE_WORD_SWAP;
+#else
+#error "this driver doesn't run on big-endian machines yet!"
+#endif
X
X mac1 = 0;
X for(i = 0; i < 4; i++){
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.2.0-pre7/linux/drivers/net/eepro100.c Sun Nov 8 14:03:00 1998
+++ linux/drivers/net/eepro100.c Fri Jan 15 14:36:21 1999
@@ -1110,6 +1110,7 @@
X /* Free the original skb. */
X if (sp->tx_skbuff[entry]) {
X sp->stats.tx_packets++; /* Count only user packets. */
+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; /* Count transmitted bytes */
X dev_free_skb(sp->tx_skbuff[entry]);
X sp->tx_skbuff[entry] = 0;
X } else if ((sp->tx_ring[entry].status&0x70000) == CmdNOp << 16)
@@ -1228,6 +1229,7 @@
X skb->protocol = eth_type_trans(skb, dev);
X netif_rx(skb);
X sp->stats.rx_packets++;
+ sp->stats.rx_bytes += pkt_len; /* Count received bytes */
X }
X entry = (++sp->cur_rx) % RX_RING_SIZE;
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v2.2.0-pre7/linux/drivers/net/eexpress.c Fri Jan 8 22:36:07 1999
+++ linux/drivers/net/eexpress.c Thu Jan 14 10:31:41 1999
@@ -97,6 +97,7 @@
X #include <asm/system.h>
X #include <asm/bitops.h>
X #include <asm/io.h>
+#include <asm/irq.h>


X #include <linux/delay.h>
X #include <linux/errno.h>

X #include <linux/init.h>
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/hamradio/baycom_ser_fdx.c linux/drivers/net/hamradio/baycom_ser_fdx.c
--- v2.2.0-pre7/linux/drivers/net/hamradio/baycom_ser_fdx.c Tue Jun 9 11:57:29 1998
+++ linux/drivers/net/hamradio/baycom_ser_fdx.c Sun Jan 17 18:28:06 1999
@@ -83,6 +83,7 @@
X #include <linux/netdevice.h>
X #include <linux/hdlcdrv.h>
X #include <linux/baycom.h>
+#include <linux/version.h>
X
X /* --------------------------------------------------------------------- */
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/hamradio/baycom_ser_hdx.c linux/drivers/net/hamradio/baycom_ser_hdx.c
--- v2.2.0-pre7/linux/drivers/net/hamradio/baycom_ser_hdx.c Tue Jun 9 11:57:29 1998
+++ linux/drivers/net/hamradio/baycom_ser_hdx.c Sun Jan 17 18:28:06 1999
@@ -72,6 +72,7 @@
X #include <linux/netdevice.h>
X #include <linux/hdlcdrv.h>
X #include <linux/baycom.h>
+#include <linux/version.h>
X
X /* --------------------------------------------------------------------- */
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/hamradio/soundmodem/sm.c linux/drivers/net/hamradio/soundmodem/sm.c
--- v2.2.0-pre7/linux/drivers/net/hamradio/soundmodem/sm.c Fri Nov 27 13:09:24 1998
+++ linux/drivers/net/hamradio/soundmodem/sm.c Sun Jan 17 18:28:06 1999
@@ -61,6 +61,7 @@
X #include <asm/bitops.h>


X #include <linux/delay.h>
X #include <linux/errno.h>

+#include <linux/version.h>
X #include "sm.h"
X
X /* --------------------------------------------------------------------- */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/ltpc.c linux/drivers/net/ltpc.c
--- v2.2.0-pre7/linux/drivers/net/ltpc.c Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/ltpc.c Fri Jan 15 14:36:21 1999
@@ -1335,7 +1335,7 @@
X /* if it's in process, wait a bit for it to finish */
X timeout = jiffies+HZ;
X add_timer(&ltpc_timer);
- while(del_timer(&ltpc_timer) && (timeout > jiffies))
+ while(del_timer(&ltpc_timer) && time_after(timeout, jiffies))
X {
X add_timer(&ltpc_timer);
X schedule();
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.2.0-pre7/linux/drivers/net/pcnet32.c Sat Sep 5 16:46:40 1998
+++ linux/drivers/net/pcnet32.c Sun Jan 17 18:28:06 1999
@@ -1,6 +1,6 @@
X /* pcnet32.c: An AMD PCnet32 ethernet driver for linux. */
X /*
- * Copyright 1996,97,98 Thomas Bogendoerfer
+ * Copyright 1996-1999 Thomas Bogendoerfer
X *
X * Derived from the lance driver written 1993,1994,1995 by Donald Becker.
X *
@@ -13,7 +13,7 @@
X * This driver is for PCnet32 and PCnetPCI based ethercards
X */
X
-static const char *version = "pcnet32.c:v1.02 3.9.98 tsbo...@alpha.franken.de\n";
+static const char *version = "pcnet32.c:v1.11 17.1.99 tsbo...@alpha.franken.de\n";
X
X #include <linux/config.h>
X #include <linux/module.h>
@@ -51,6 +51,17 @@
X static const int max_interrupt_work = 20;
X static const int rx_copybreak = 200;
X
+#define PORT_AUI 0x00
+#define PORT_10BT 0x01
+#define PORT_GPSI 0x02
+#define PORT_MII 0x03
+
+#define PORT_PORTSEL 0x03
+#define PORT_ASEL 0x04
+#define PORT_FD 0x80
+
+static int options = PORT_ASEL; /* port selection */
+
X /*
X * Theory of Operation
X *
@@ -101,6 +112,10 @@
X * v1.01: do ring dumps, only when debugging the driver
X * increased the transmit timeout
X * v1.02: fixed memory leak in pcnet32_init_ring()
+ * v1.10: workaround for stopped transmitter
+ * added port selection for modules
+ * detect special T1/E1 WAN card and setup port selection
+ * v1.11: fixed wrong checking of Tx errors
X */
X
X
@@ -176,8 +191,9 @@
X int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
X struct net_device_stats stats;
X char tx_full;
- unsigned long lock;
- char shared_irq; /* shared irq possible */
+ int options;
+ int shared_irq:1, /* shared irq possible */
+ full_duplex:1; /* full duplex possible */
X #ifdef MODULE
X struct device *next;
X #endif
@@ -250,11 +266,13 @@
X unsigned int ioaddr = *port;
X
X if ( check_region(ioaddr, PCNET32_TOTAL_SIZE) == 0) {
- if (pcnet32_probe1(dev, ioaddr, 0, 0) == 0)
+ /* check if there is really a pcnet chip on that ioaddr */
+ if ((inb(ioaddr + 14) == 0x57) &&
+ (inb(ioaddr + 15) == 0x57) &&
+ (pcnet32_probe1(dev, ioaddr, 0, 0) == 0))


X return 0;
X }
X }

-
X return ENODEV;
X }
X
@@ -263,13 +281,9 @@
X __initfunc(static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line, int shared))
X {
X struct pcnet32_private *lp;
- int i;
+ int i,full_duplex = 0;
X char *chipname;
X
- /* check if there is really a pcnet chip on that ioaddr */
- if ((inb(ioaddr + 14) != 0x57) || (inb(ioaddr + 15) != 0x57))
- return ENODEV;
-
X inw(ioaddr+PCNET32_RESET); /* Reset the PCNET32 */
X
X outw(0x0000, ioaddr+PCNET32_ADDR); /* Switch to window 0 */
@@ -295,16 +309,22 @@
X chipname = "PCnet/PCI 79C970";
X break;
X case 0x2430:
- chipname = "PCnet32";
+ if (shared)
+ chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */
+ else
+ chipname = "PCnet/32 79C965";
X break;
X case 0x2621:
X chipname = "PCnet/PCI II 79C970A";
+ full_duplex = 1;
X break;
X case 0x2623:
X chipname = "PCnet/FAST 79C971";
+ full_duplex = 1;
X break;
X case 0x2624:
X chipname = "PCnet/FAST+ 79C972";
+ full_duplex = 1;


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 05'
echo 'File patch-2.2.0-pre8 is continued in part 06'
echo 06 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part07

#!/bin/sh
# this is part 07 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 07; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&
+

+ if (msgOffset == 0xFFFFFFFF)
+ {
+ kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ /* virtual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0xff;
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_BROADCAST_MODE;
+ /* phys address to return status - area right after PAB */
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] != 0xff)
+ break;
+
+ if (!timeout--)
+ {
+ kprintf("Timeout waiting for promiscuous mode from adapter\n");
+ kprintf("0x%08.8ulx\n", p32[0]);
+ return RC_RTN_NO_LINK_SPEED;
+ }
+ }
+
+ /* get mode */
+ *pMode = (U8)((volatile PU8)p32)[0] & 0x0f;
+
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCGetLinkSpeed()
+**
+** get ethernet link speed.
+**
+** 0 = Unknown
+** 1 = Full Duplex 100BaseT
+** 2 = Half duplex 100BaseT
+** 3 = Full Duplex 10BaseT
+** 4 = Half duplex 10BaseT
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+ U8 IOPLinkSpeed;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+
+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ /* virtual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0xff;
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED;
+ /* phys address to return status - area right after PAB */
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] != 0xff)
+ break;
+
+ if (!timeout--)
+ {
+ kprintf("Timeout waiting for link speed from IOP\n");
+ kprintf("0x%08.8ulx\n", p32[0]);
+ return RC_RTN_NO_LINK_SPEED;
+ }
+ }
+
+ /* get Link speed */
+ IOPLinkSpeed = (U8)((volatile PU8)p32)[0] & 0x0f;
+
+ *pLinkSpeedCode= IOPLinkSpeed;
+
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCReportDriverCapability(U16 AdapterID, U32 capability)
+**
+** Currently defined bits:
+** WARM_REBOOT_CAPABLE 0x01
+**
+** =========================================================================
+*/
+RC_RETURN
+RCReportDriverCapability(U16 AdapterID, U32 capability)
+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_REPORT_DRIVER_CAPABILITY;
+ pMsg[5] = capability;
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+
+ return RC_RTN_NO_ERROR ;
+}
+
+/*
+** =========================================================================
+** RCGetFirmwareVer()
+**
+** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ kprintf("RCGetFirmwareVer(): Inbound Free Q empty!\n");
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ /* virtual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0xff;
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV;
+ /* phys address to return status - area right after PAB */
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] != 0xff)
+ break;
+
+ if (!timeout--)
+ {
+ kprintf("Timeout waiting for link speed from IOP\n");
+ return RC_RTN_NO_FIRM_VER;
+ }
+ }
+
+ strcpy(pFirmString, (PU8)p32);
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCResetLANCard()
+**
+** ResourceFlags indicates whether to return buffer resource explicitly
+** to host or keep and reuse.
+** CallbackFunction (if not NULL) is the function to be called when
+** reset is complete.
+** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
+** reset is done (if not NULL).
+**
+** =========================================================================
+*/
+RC_RETURN
+RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+{
+ unsigned long off;
+ unsigned long *pMsg;
+ PPAB pPab;
+ int i;
+ long timeout = 0;
+
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pPab->pCallbackFunc = CallbackFunction;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup message */
+ pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_LAN_RESET << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = ResourceFlags << 16; /* resource flags */
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+
+ if (CallbackFunction == (PFNCALLBACK)NULL)
+ {
+ /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
+ or until timer goes off */
+ while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
+ {
+ RCProcI2OMsgQ(AdapterID);
+ for (i = 0; i < 100000; i++) /* please don't hog the bus!!! */
+ ;
+ timeout++;
+ if (timeout > 10000)
+ {
+ break;
+ }
+ }
+ if (ReturnAddr != (PU32)NULL)
+ *ReturnAddr = (U32)pPab->pCallbackFunc;
+ }
+
+ return RC_RTN_NO_ERROR ;
+}
+/*
+** =========================================================================
+** RCResetIOP()
+**
+** Send StatusGet Msg, wait for results return directly to buffer.
+**
+** =========================================================================
+*/
+RC_RETURN
+RCResetIOP(U16 AdapterID)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ PPAB pPab;
+ volatile PU32 p32;
+
+ pPab = PCIAdapterBlock[AdapterID];
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_EXEC_IOP_RESET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+ pMsg[2] = 0; /* universal context */
+ pMsg[3] = 0; /* universal context */
+ pMsg[4] = 0; /* universal context */
+ pMsg[5] = 0; /* universal context */
+ /* phys address to return status - area right after PAB */
+ pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+ pMsg[7] = 0;
+ pMsg[8] = 1; /* return 1 byte */
+
+ /* virual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0;
+ p32[1] = 0;
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] || p32[1])
+ break;
+
+ if (!timeout--)
+ {
+ printk("RCResetIOP timeout\n");
+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCShutdownLANCard()
+**
+** ResourceFlags indicates whether to return buffer resource explicitly
+** to host or keep and reuse.
+** CallbackFunction (if not NULL) is the function to be called when
+** shutdown is complete.
+** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
+** shutdown is done (if not NULL).
+**
+** =========================================================================
+*/
+RC_RETURN
+RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+{
+ volatile PU32 pMsg;
+ U32 off;
+ PPAB pPab;
+ int i;
+ long timeout = 0;
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pPab->pCallbackFunc = CallbackFunction;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup message */
+ pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_LAN_SHUTDOWN << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = ResourceFlags << 16; /* resource flags */
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+
+ if (CallbackFunction == (PFNCALLBACK)NULL)
+ {
+ /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
+ or until timer goes off */
+ while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
+ {
+ RCProcI2OMsgQ(AdapterID);
+ for (i = 0; i < 100000; i++) /* please don't hog the bus!!! */
+ ;
+ timeout++;
+ if (timeout > 10000)
+ {
+ printk("RCShutdownLANCard(): timeout\n");
+ break;
+ }
+ }
+ if (ReturnAddr != (PU32)NULL)
+ *ReturnAddr = (U32)pPab->pCallbackFunc;
+ }
+ return RC_RTN_NO_ERROR ;
+}
+
+
+/*
+** =========================================================================
+** RCSetRavlinIPandMask()
+**
+** Set the Ravlin 45/PCI cards IP address and network mask.
+**
+** IP address and mask must be in network byte order.
+** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
+** 0x04030201 and 0x00FFFFFF on a little endian machine.
+**
+** =========================================================================
+*/
+RC_RETURN
+RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask)
+{
+ volatile PU32 pMsg;
+ U32 off;
+ PPAB pPab;
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK;
+ pMsg[5] = ipAddr;
+ pMsg[6] = netMask;
+
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+ return RC_RTN_NO_ERROR ;
+
+}
+
+/*
+** =========================================================================
+** RCGetRavlinIPandMask()
+**
+** get the IP address and MASK from the card
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask,
+ PFNWAITCALLBACK WaitCallback)
+{
+ unsigned i, timeout;
+ U32 off;
+ PU32 pMsg, p32;
+ PPAB pPab;
+ PATU p_atu;
+
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);
+#endif /* DEBUG */
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ p_atu = pPab->p_atu;
+ off = p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ *p32 = 0xFFFFFFFF;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
+#endif /* DEBUG */
+ /* setup private message */
+ pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x218; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK;
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ p_atu->InQueue = off; /* send it to the I2O device */
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
+#endif /* DEBUG */
+
+ /* wait for the rcpci45 board to update the info */
+ timeout = 100000;
+ while (0xffffffff == *p32)
+ {
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++)
+ ;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: Timeout\n");
+#endif /* DEBUG */
+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: after time out\n", \
+ "p32[0] (IpAddr) 0x%08.8ulx, p32[1] (IPmask) 0x%08.8ulx\n", p32[0], p32[1]);
+#endif /* DEBUG */
+
+ /* send IP and mask to user's space */
+ *pIpAddr = p32[0];
+ *pNetMask = p32[1];
+
+
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);
+#endif /* DEBUG */
+
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** /////////////////////////////////////////////////////////////////////////
+** /////////////////////////////////////////////////////////////////////////
+**
+** local functions
+**
+** /////////////////////////////////////////////////////////////////////////
+** /////////////////////////////////////////////////////////////////////////
+*/
+
+/*
+** =========================================================================
+** SendI2OOutboundQInitMsg()
+**
+** =========================================================================
+*/
+static int
+SendI2OOutboundQInitMsg(PPAB pPab)
+{
+ U32 msgOffset, timeout, phyOutQFrames, i;
+ volatile PU32 pMsg;
+ volatile PU32 p32;
+
+
+
+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+#ifdef DEBUG
+ kprintf("SendI2OOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
+#endif /* DEBUG */
+
+ pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6;
+ pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = 0x106; /* transaction context */
+ pMsg[4] = 4096; /* Host page frame size */
+ pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; /* outbound msg frame size and Initcode */
+ pMsg[6] = 0xD0000004; /* simple sgl element LE, EOB */
+ /* phys address to return status - area right after PAB */
+ pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ /* virual pointer to return buffer - clear first two dwords */
+ p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0;
+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 100000;
+ while(1)
+ {
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0])
+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("Timeout wait for InitOutQ InPrgress status from IOP\n");
+#endif /* DEBUG */
+ return RC_RTN_NO_I2O_STATUS;
+ }
+ }
+
+ timeout = 100000;
+ while(1)
+ {
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE)
+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("Timeout wait for InitOutQ Complete status from IOP\n");
+#endif /* DEBUG */
+ return RC_RTN_NO_I2O_STATUS;
+ }
+ }
+
+ /* load PCI outbound free Q with MF physical addresses */
+ phyOutQFrames = pPab->outMsgBlockPhyAddr;
+
+ for (i = 0; i < NMBR_MSG_FRAMES; i++)
+ {
+ pPab->p_atu->OutQueue = phyOutQFrames;
+ phyOutQFrames += MSG_FRAME_SIZE;
+ }
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** GetI2OStatus()
+**
+** Send StatusGet Msg, wait for results return directly to buffer.
+**
+** =========================================================================
+*/
+static int
+GetI2OStatus(PPAB pPab)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+
+
+ msgOffset = pPab->p_atu->InQueue;
+#ifdef DEBUG
+ printk("GetI2OStatus: msg offset = 0x%x\n", msgOffset);
+#endif /* DEBUG */
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("GetI2OStatus(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_EXEC_STATUS_GET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+ pMsg[2] = 0; /* universal context */
+ pMsg[3] = 0; /* universal context */
+ pMsg[4] = 0; /* universal context */
+ pMsg[5] = 0; /* universal context */
+ /* phys address to return status - area right after PAB */
+ pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+ pMsg[7] = 0;
+ pMsg[8] = 88; /* return 88 bytes */
+
+ /* virual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0;
+ p32[1] = 0;
+
+#ifdef DEBUG
+ kprintf("GetI2OStatus - pMsg:0x%08.8ulx, msgOffset:0x%08.8ulx, [1]:0x%08.8ulx, [6]:0x%08.8ulx\n",
+ pMsg, msgOffset, pMsg[1], pMsg[6]);
+#endif /* DEBUG */
+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+
+#ifdef DEBUG
+ kprintf("Return status to p32 = 0x%08.8ulx\n", p32);
+#endif /* DEBUG */
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] && p32[1])
+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("Timeout waiting for status from IOP\n");
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
+#endif /* DEBUG */
+ return RC_RTN_NO_I2O_STATUS;
+ }
+ }
+
+#ifdef DEBUG
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
+#endif /* DEBUG */
+ /* get IOP state */
+ pPab->IOPState = ((volatile PU8)p32)[10];
+ pPab->InboundMFrameSize = ((volatile PU16)p32)[6];
+
+#ifdef DEBUG
+ kprintf("IOP state 0x%02.2x InFrameSize = 0x%04.4x\n",
+ pPab->IOPState, pPab->InboundMFrameSize);
+#endif /* DEBUG */
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** SendEnableSysMsg()
+**
+**
+** =========================================================================
+*/
+static int
+SendEnableSysMsg(PPAB pPab)
+{
+ U32 msgOffset; // timeout;
+ volatile PU32 pMsg;
+
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("SendEnableSysMsg(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+#ifdef DEBUG
+ kprintf("SendEnableSysMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
+#endif /* DEBUG */
+
+ pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_EXEC_SYS_ENABLE << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = 0x110; /* transaction context */
+ pMsg[4] = 0x50657465; /* RedCreek Private */
+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** FillI2OMsgFromTCB()
+**
+** inputs pMsgU32 - virual pointer (mapped to physical) of message frame
+** pXmitCntrlBlock - pointer to caller buffer control block.
+**
+** fills in LAN SGL after Transaction Control Word or Bucket Count.
+** =========================================================================
+*/
+static int
+FillI2OMsgSGLFromTCB(PU32 pMsgFrame, PRCTCB pTransCtrlBlock)
+{
+ unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags;
+ PU32 pTCB, pMsg;
+
+ /* SGL element flags */
+#define EOB 0x40000000
+#define LE 0x80000000
+#define SIMPLE_SGL 0x10000000
+#define BC_PRESENT 0x01000000
+
+ pTCB = (PU32)pTransCtrlBlock;
+ pMsg = pMsgFrame;
+ nmbrDwords = 0;
+
+#ifdef DEBUG
+ kprintf("FillI2OMsgSGLFromTCBX\n");
+ kprintf("TCB 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+ pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]);
+ kprintf("pTCB 0x%08.8ulx, pMsg 0x%08.8ulx\n", pTCB, pMsg);
+#endif /* DEBUG */
+
+ nmbrBuffers = *pTCB++;
+
+ if (!nmbrBuffers)
+ {


+ return -1;
+ }
+

+ do
+ {
+ context = *pTCB++; /* buffer tag (context) */
+ nmbrSeg = *pTCB++; /* number of segments */
+
+ if (!nmbrSeg)
+ {


+ return -1;
+ }
+

+ flags = SIMPLE_SGL | BC_PRESENT;
+
+ if (1 == nmbrSeg)
+ {
+ flags |= EOB;
+
+ if (1 == nmbrBuffers)
+ flags |= LE;
+ }
+
+ /* 1st SGL buffer element has context */
+ pMsg[0] = pTCB[0] | flags ; /* send over count (segment size) */
+ pMsg[1] = context;
+ pMsg[2] = pTCB[1]; /* send buffer segment physical address */
+ nmbrDwords += 3;
+ pMsg += 3;
+ pTCB += 2;
+
+
+ if (--nmbrSeg)
+ {
+ do
+ {
+ flags = SIMPLE_SGL;
+
+ if (1 == nmbrSeg)
+ {
+ flags |= EOB;
+
+ if (1 == nmbrBuffers)
+ flags |= LE;
+ }
+
+ pMsg[0] = pTCB[0] | flags; /* send over count */
+ pMsg[1] = pTCB[1]; /* send buffer segment physical address */
+ nmbrDwords += 2;
+ pTCB += 2;
+ pMsg += 2;
+
+ } while (--nmbrSeg);
+ }
+
+ } while (--nmbrBuffers);
+
+ return nmbrDwords;
+}
+
+
+/*
+** =========================================================================
+** ProcessOutboundI2OMsg()
+**
+** process I2O reply message
+** * change to msg structure *
+** =========================================================================
+*/
+static void
+ProcessOutboundI2OMsg(PPAB pPab, U32 phyAddrMsg)
+{
+ PU8 p8Msg;
+ PU32 p32;
+ // U16 count;
+
+
+ p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
+ p32 = (PU32)p8Msg;
+
+#ifdef DEBUG
+ kprintf("VXD: ProcessOutboundI2OMsg - pPab 0x%08.8ulx, phyAdr 0x%08.8ulx, linAdr 0x%08.8ulx\n", pPab, phyAddrMsg, p8Msg);
+ kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+ kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+#endif /* DEBUG */
+
+ if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS)
+ {
+#ifdef DEBUG
+ kprintf("Message reply status not success\n");
+#endif /* DEBUG */
+ return;
+ }
+
+ switch (p8Msg[7] ) /* function code byte */
+ {
+ case I2O_EXEC_SYS_TAB_SET:
+ msgFlag = 1;
+#ifdef DEBUG
+ kprintf("Received I2O_EXEC_SYS_TAB_SET reply\n");
+#endif /* DEBUG */
+ break;
+
+ case I2O_EXEC_HRT_GET:
+ msgFlag = 1;
+#ifdef DEBUG
+ kprintf("Received I2O_EXEC_HRT_GET reply\n");
+#endif /* DEBUG */
+ break;
+
+ case I2O_EXEC_LCT_NOTIFY:
+ msgFlag = 1;
+#ifdef DEBUG
+ kprintf("Received I2O_EXEC_LCT_NOTIFY reply\n");
+#endif /* DEBUG */
+ break;
+
+ case I2O_EXEC_SYS_ENABLE:
+ msgFlag = 1;
+#ifdef DEBUG
+ kprintf("Received I2O_EXEC_SYS_ENABLE reply\n");
+#endif /* DEBUG */


+ break;
+
+ default:

+#ifdef DEBUG
+ kprintf("Received UNKNOWN reply\n");
+#endif /* DEBUG */
+ break;
+ }
+}
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/rclanmtl.h linux/drivers/net/rclanmtl.h
--- v2.2.0-pre7/linux/drivers/net/rclanmtl.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/rclanmtl.h Thu Jan 14 22:58:47 1999
@@ -0,0 +1,637 @@
+/*
+** *************************************************************************
+**
+**
+** R C L A N M T L . H $Revision: 5 $
+**
+**
+** RedCreek I2O LAN Message Transport Layer header file.
+**
+** ---------------------------------------------------------------------
+** --- Copyright (c) 1997-1999, RedCreek Communications Inc. ---
+** --- All rights reserved. ---
+** ---------------------------------------------------------------------
+**
+** File Description:
+**
+** Header file for host I2O (Intelligent I/O) LAN message transport layer
+** API and data types.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** *************************************************************************
+*/
+
+#ifndef RCLANMTL_H
+#define RCLANMTL_H
+
+/* Linux specific includes */
+#define kprintf printk
+#ifdef RC_LINUX_MODULE /* linux modules need non-library version of string functions */
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+/* PCI/45 Configuration space values */
+#define RC_PCI45_VENDOR_ID 0x4916
+#define RC_PCI45_DEVICE_ID 0x1960
+
+
+ /* RedCreek API function return values */
+#define RC_RTN_NO_ERROR 0
+#define RC_RTN_I2O_NOT_INIT 1
+#define RC_RTN_FREE_Q_EMPTY 2
+#define RC_RTN_TCB_ERROR 3
+#define RC_RTN_TRANSACTION_ERROR 4
+#define RC_RTN_ADAPTER_ALREADY_INIT 5
+#define RC_RTN_MALLOC_ERROR 6
+#define RC_RTN_ADPTR_NOT_REGISTERED 7
+#define RC_RTN_MSG_REPLY_TIMEOUT 8
+#define RC_RTN_NO_I2O_STATUS 9
+#define RC_RTN_NO_FIRM_VER 10
+#define RC_RTN_NO_LINK_SPEED 11
+
+/* Driver capability flags */
+#define WARM_REBOOT_CAPABLE 0x01
+
+ /* scalar data types */
+typedef unsigned char U8;
+typedef unsigned char* PU8;
+typedef unsigned short U16;
+typedef unsigned short* PU16;
+typedef unsigned long U32;
+typedef unsigned long* PU32;
+typedef unsigned long BF;
+typedef int RC_RETURN;
+
+
+ /*
+ ** type PFNWAITCALLBACK
+ **
+ ** pointer to void function - type used for WaitCallback in some functions
+ */
+typedef void (*PFNWAITCALLBACK)(void); /* void argument avoids compiler complaint */
+
+ /*
+ ** type PFNTXCALLBACK
+ **
+ ** Pointer to user's transmit callback function. This user function is
+ ** called from RCProcI2OMsgQ() when packet have been transmitted from buffers
+ ** given in the RCI2OSendPacket() function. BufferContext is a pointer to
+ ** an array of 32 bit context values. These are the values the user assigned
+ ** and passed in the TCB to the RCI2OSendPacket() function. PcktCount
+ ** indicates the number of buffer context values in the BufferContext[] array.
+ ** The User's TransmitCallbackFunction should recover (put back in free queue)
+ ** the packet buffers associated with the buffer context values.
+ */
+typedef void (*PFNTXCALLBACK)(U32 Status,
+ U16 PcktCount,
+ PU32 BufferContext,
+ U16 AdaterID);
+
+ /*
+ ** type PFNRXCALLBACK
+ **
+ ** Pointer to user's receive callback function. This user function
+ ** is called from RCProcI2OMsgQ() when packets have been received into
+ ** previously posted packet buffers throught the RCPostRecvBuffers() function.
+ ** The received callback function should process the Packet Descriptor Block
+ ** pointed to by PacketDescBlock. See Packet Decription Block below.
+ */
+typedef void (*PFNRXCALLBACK)(U32 Status,
+ U8 PktCount,
+ U32 BucketsRemain,
+ PU32 PacketDescBlock,
+ U16 AdapterID);
+
+ /*
+ ** type PFNCALLBACK
+ **
+ ** Pointer to user's generic callback function. This user function
+ ** can be passed to LANReset or LANShutdown and is called when the
+ ** the reset or shutdown is complete.
+ ** Param1 and Param2 are invalid for LANReset and LANShutdown.
+ */
+typedef void (*PFNCALLBACK)(U32 Status,
+ U32 Param1,
+ U32 Param2,
+ U16 AdapterID);
+
+/*
+** Status - Transmit and Receive callback status word
+**
+** A 32 bit Status is returned to the TX and RX callback functions. This value
+** contains both the reply status and the detailed status as follows:
+**
+** 32 24 16 0
+** +------+------+------------+
+** | Reply| | Detailed |
+** |Status| 0 | Status |
+** +------+------+------------+
+**
+** Reply Status and Detailed Status of zero indicates No Errors.
+*/
+ /* reply message status defines */
+#define I2O_REPLY_STATUS_SUCCESS 0x00
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
+#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0A
+
+
+/* DetailedStatusCode defines */
+#define I2O_LAN_DSC_SUCCESS 0x0000
+#define I2O_LAN_DSC_DEVICE_FAILURE 0x0001
+#define I2O_LAN_DSC_DESTINATION_NOT_FOUND 0x0002
+#define I2O_LAN_DSC_TRANSMIT_ERROR 0x0003
+#define I2O_LAN_DSC_TRANSMIT_ABORTED 0x0004
+#define I2O_LAN_DSC_RECEIVE_ERROR 0x0005
+#define I2O_LAN_DSC_RECEIVE_ABORTED 0x0006
+#define I2O_LAN_DSC_DMA_ERROR 0x0007
+#define I2O_LAN_DSC_BAD_PACKET_DETECTED 0x0008
+#define I2O_LAN_DSC_OUT_OF_MEMORY 0x0009
+#define I2O_LAN_DSC_BUCKET_OVERRUN 0x000A
+#define I2O_LAN_DSC_IOP_INTERNAL_ERROR 0x000B
+#define I2O_LAN_DSC_CANCELED 0x000C
+#define I2O_LAN_DSC_INVALID_TRANSACTION_CONTEXT 0x000D
+#define I2O_LAN_DSC_DESTINATION_ADDRESS_DETECTED 0x000E
+#define I2O_LAN_DSC_DESTINATION_ADDRESS_OMITTED 0x000F
+#define I2O_LAN_DSC_PARTIAL_PACKET_RETURNED 0x0010
+
+
+/*
+** Packet Description Block (Received packets)
+**
+** A pointer to this block structure is returned to the ReceiveCallback
+** function. It contains the list of packet buffers which have either been
+** filled with a packet or returned to host due to a LANReset function.
+** Currently there will only be one packet per receive bucket (buffer) posted.
+**
+** 32 24 0
+** +-----------------------+ -\
+** | Buffer 1 Context | \
+** +-----------------------+ \
+** | 0xC0000000 | / First Bucket Descriptor
+** +-----+-----------------+ /
+** | 0 | packet 1 length | /
+** +-----------------------+ -\
+** | Buffer 2 Context | \
+** +-----------------------+ \
+** | 0xC0000000 | / Second Bucket Descriptor
+** +-----+-----------------+ /
+** | 0 | packet 2 length | /
+** +-----+-----------------+ -
+** | ... | ----- more bucket descriptors
+** +-----------------------+ -\
+** | Buffer n Context | \
+** +-----------------------+ \
+** | 0xC0000000 | / Last Bucket Descriptor
+** +-----+-----------------+ /
+** | 0 | packet n length | /
+** +-----+-----------------+ -
+**
+** Buffer Context values are those given to adapter in the TCB on calls to
+** RCPostRecvBuffers().
+**
+*/
+
+
+
+/*
+** Transaction Control Block (TCB) structure
+**
+** A structure like this is filled in by the user and passed by reference to
+** RCI2OSendPacket() and RCPostRecvBuffers() functions. Minimum size is five
+** 32-bit words for one buffer with one segment descriptor.
+** MAX_NMBR_POST_BUFFERS_PER_MSG defines the maximum single segment buffers
+** that can be described in a given TCB.
+**
+** 32 0
+** +-----------------------+
+** | Buffer Count | Number of buffers in the TCB
+** +-----------------------+
+** | Buffer 1 Context | first buffer reference
+** +-----------------------+
+** | Buffer 1 Seg Count | number of segments in buffer
+** +-----------------------+
+** | Buffer 1 Seg Desc 1 | first segment descriptor (size, physical address)
+** +-----------------------+
+** | ... | more segment descriptors (size, physical address)
+** +-----------------------+
+** | Buffer 1 Seg Desc n | last segment descriptor (size, physical address)
+** +-----------------------+
+** | Buffer 2 Context | second buffer reference
+** +-----------------------+
+** | Buffer 2 Seg Count | number of segments in buffer
+** +-----------------------+
+** | Buffer 2 Seg Desc 1 | segment descriptor (size, physical address)
+** +-----------------------+
+** | ... | more segment descriptors (size, physical address)
+** +-----------------------+
+** | Buffer 2 Seg Desc n |
+** +-----------------------+
+** | ... | more buffer descriptor blocks ...
+** +-----------------------+
+** | Buffer n Context |
+** +-----------------------+
+** | Buffer n Seg Count |
+** +-----------------------+
+** | Buffer n Seg Desc 1 |
+** +-----------------------+
+** | ... |
+** +-----------------------+
+** | Buffer n Seg Desc n |
+** +-----------------------+
+**
+**
+** A TCB for one contigous packet buffer would look like the following:
+**
+** 32 0
+** +-----------------------+
+** | 1 | one buffer in the TCB
+** +-----------------------+
+** | <user's Context> | user's buffer reference
+** +-----------------------+
+** | 1 | one segment buffer
+** +-----------------------+ _
+** | <buffer size> | size \
+** +-----------------------+ \ segment descriptor
+** | <physical address> | physical address of buffer /
+** +-----------------------+ _/
+**
+*/
+
+ /* Buffer Segment Descriptor */
+typedef struct
+{
+ U32 size;
+ U32 phyAddress;
+}
+ BSD, *PBSD;
+
+typedef PU32 PRCTCB;
+/*
+** -------------------------------------------------------------------------
+** Exported functions comprising the API to the LAN I2O message transport layer
+** -------------------------------------------------------------------------
+*/
+
+
+ /*
+ ** InitRCI2OMsgLayer()
+ **
+ ** Called once prior to using the I2O LAN message transport layer. User
+ ** provides both the physical and virual address of a locked page buffer
+ ** that is used as a private buffer for the RedCreek I2O message
+ ** transport layer. This buffer must be a contigous memory block of a
+ ** minimum of 16K bytes and long word aligned. The user also must provide
+ ** the base address of the RedCreek PCI adapter assigned by BIOS or operating
+ ** system. The user provided value AdapterID is a zero based index of the
+ ** Ravlin 45/PCI adapter. This interface number is used in all subsequent API
+ ** calls to identify which adpapter for which the function is intended.
+ ** Up to sixteen interfaces are supported with this API.
+ **
+ ** Inputs: AdapterID - interface number from 0 to 15
+ ** pciBaseAddr - virual base address of PCI (set by BIOS)
+ ** p_msgbuf - virual address to private message block (min. 16K)
+ ** p_phymsgbuf - physical address of private message block
+ ** TransmitCallbackFunction - address of user's TX callback function
+ ** ReceiveCallbackFunction - address of user's RX callback function
+ **
+ */
+RC_RETURN RCInitI2OMsgLayer(U16 AdapterID, U32 pciBaseAddr,
+ PU8 p_msgbuf, PU8 p_phymsgbuf,
+ PFNTXCALLBACK TransmitCallbackFunction,
+ PFNRXCALLBACK ReceiveCallbackFunction,
+ PFNCALLBACK RebootCallbackFunction);
+
+ /*
+ ** RCSetRavlinIPandMask()
+ **
+ ** Set the Ravlin 45/PCI cards IP address and network mask.
+ **
+ ** IP address and mask must be in network byte order.
+ ** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
+ ** 0x04030201 and 0x00FFFFFF on a little endian machine.
+ **
+ */
+RC_RETURN RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask);
+
+
+/*
+** =========================================================================
+** RCGetRavlinIPandMask()
+**
+** get the IP address and MASK from the card
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask,
+ PFNWAITCALLBACK WaitCallback);
+
+ /*
+ ** RCProcI2OMsgQ()
+ **
+ ** Called from user's polling loop or Interrupt Service Routine for a PCI
+ ** interrupt from the RedCreek PCI adapter. User responsible for determining
+ ** and hooking the PCI interrupt. This function will call the registered
+ ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
+ ** if a TX or RX transaction has completed.
+ */
+void RCProcI2OMsgQ(U16 AdapterID);
+
+
+ /*
+ ** Disable and Enable I2O interrupts. I2O interrupts are enabled at Init time
+ ** but can be disabled and re-enabled through these two function calls.
+ ** Packets will still be put into any posted recieved buffers and packets will
+ ** be sent through RCI2OSendPacket() functions. Disabling I2O interrupts
+ ** will prevent hardware interrupt to host even though the outbound I2O msg
+ ** queue is not emtpy.
+ */
+RC_RETURN RCEnableI2OInterrupts(U16 adapterID);
+RC_RETURN RCDisableI2OInterrupts(U16 AdapterID);
+
+
+ /*
+ ** RCPostRecvBuffers()
+ **
+ ** Post user's page locked buffers for use by the PCI adapter to
+ ** return ethernet packets received from the LAN. Transaction Control Block,
+ ** provided by user, contains buffer descriptor(s) which includes a buffer
+ ** context number along with buffer size and physical address. See TCB above.
+ ** The buffer context and actual packet length are returned to the
+ ** ReceiveCallbackFunction when packets have been received. Buffers posted
+ ** to the RedCreek adapter are considered owned by the adapter until the
+ ** context is return to user through the ReceiveCallbackFunction.
+ */
+RC_RETURN RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransactionCtrlBlock);
+#define MAX_NMBR_POST_BUFFERS_PER_MSG 32
+
+ /*
+ ** RCI2OSendPacket()
+ **
+ ** Send user's ethernet packet from a locked page buffer.
+ ** Packet must have full MAC header, however without a CRC.
+ ** Initiator context is a user provided value that is returned
+ ** to the TransmitCallbackFunction when packet buffer is free.
+ ** Transmit buffer are considered owned by the adapter until context's
+ ** returned to user through the TransmitCallbackFunction.
+ */
+RC_RETURN RCI2OSendPacket(U16 AdapterID,
+ U32 context,
+ PRCTCB pTransactionCtrlBlock);
+
+
+ /* Ethernet Link Statistics structure */
+typedef struct tag_RC_link_stats
+{
+ U32 TX_good; /* good transmit frames */
+ U32 TX_maxcol; /* frames not TX due to MAX collisions */
+ U32 TX_latecol; /* frames not TX due to late collisions */
+ U32 TX_urun; /* frames not TX due to DMA underrun */
+ U32 TX_crs; /* frames TX with lost carrier sense */
+ U32 TX_def; /* frames deferred due to activity on link */
+ U32 TX_singlecol; /* frames TX with one and only on collision */
+ U32 TX_multcol; /* frames TX with more than one collision */
+ U32 TX_totcol; /* total collisions detected during TX */
+ U32 Rcv_good; /* good frames received */
+ U32 Rcv_CRCerr; /* frames RX and discarded with CRC errors */
+ U32 Rcv_alignerr; /* frames RX with alignment and CRC errors */
+ U32 Rcv_reserr; /* good frames discarded due to no RX buffer */
+ U32 Rcv_orun; /* RX frames lost due to FIFO overrun */
+ U32 Rcv_cdt; /* RX frames with collision during RX */
+ U32 Rcv_runt; /* RX frames shorter than 64 bytes */
+}
+ RCLINKSTATS, *P_RCLINKSTATS;
+
+ /*
+ ** RCGetLinkStatistics()
+ **
+ ** Returns link statistics in user's structure at address StatsReturnAddr
+ ** If given, not NULL, the function WaitCallback is called during the wait
+ ** loop while waiting for the adapter to respond.
+ */
+RC_RETURN RCGetLinkStatistics(U16 AdapterID,
+ P_RCLINKSTATS StatsReturnAddr,
+ PFNWAITCALLBACK WaitCallback);
+
+ /*
+ ** RCGetLinkStatus()
+ **
+ ** Return link status, up or down, to user's location addressed by ReturnAddr.
+ ** If given, not NULL, the function WaitCallback is called during the wait
+ ** loop while waiting for the adapter to respond.
+ */
+RC_RETURN RCGetLinkStatus(U16 AdapterID,
+ PU32 pReturnStatus,
+ PFNWAITCALLBACK WaitCallback);
+
+ /* Link Status defines - value returned in pReturnStatus */
+#define RC_LAN_LINK_STATUS_DOWN 0
+#define RC_LAN_LINK_STATUS_UP 1
+
+ /*
+ ** RCGetMAC()
+ **
+ ** Get the current MAC address assigned to user. RedCreek Ravlin 45/PCI
+ ** has two MAC addresses. One which is private to the PCI Card, and
+ ** another MAC which is given to the user as its link layer MAC address. The
+ ** adapter runs in promiscous mode because of the dual address requirement.
+ ** The MAC address is returned to the unsigned char array pointer to by mac.
+ */
+RC_RETURN RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback);
+
+ /*
+ ** RCSetMAC()
+ **
+ ** Set a new user port MAC address. This address will be returned on
+ ** subsequent RCGetMAC() calls.
+ */
+RC_RETURN RCSetMAC(U16 AdapterID, PU8 mac);
+
+ /*
+ ** RCSetLinkSpeed()
+ **
+ ** set adapter's link speed based on given input code.
+ */
+RC_RETURN RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode);
+ /* Set link speed codes */
+#define LNK_SPD_AUTO_NEG_NWAY 0
+#define LNK_SPD_100MB_FULL 1
+#define LNK_SPD_100MB_HALF 2
+#define LNK_SPD_10MB_FULL 3
+#define LNK_SPD_10MB_HALF 4
+
+
+
+
+ /*
+ ** RCGetLinkSpeed()
+ **
+ ** Return link speed code.
+ */
+ /* Return link speed codes */
+#define LNK_SPD_UNKNOWN 0
+#define LNK_SPD_100MB_FULL 1
+#define LNK_SPD_100MB_HALF 2
+#define LNK_SPD_10MB_FULL 3
+#define LNK_SPD_10MB_HALF 4
+
+RC_RETURN
+RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
+/*
+** =========================================================================
+** RCSetPromiscuousMode(U16 AdapterID, U16 Mode)
+**
+** Defined values for Mode:
+** 0 - turn off promiscuous mode
+** 1 - turn on promiscuous mode
+**
+** =========================================================================
+*/
+#define PROMISCUOUS_MODE_OFF 0
+#define PROMISCUOUS_MODE_ON 1
+RC_RETURN
+RCSetPromiscuousMode(U16 AdapterID, U16 Mode);
+/*
+** =========================================================================
+** RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+**
+** get promiscuous mode setting
+**
+** Possible return values placed in pMode:
+** 0 = promisuous mode not set
+** 1 = promisuous mode is set
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+
+/*
+** =========================================================================
+** RCSetBroadcastMode(U16 AdapterID, U16 Mode)
+**
+** Defined values for Mode:
+** 0 - turn off promiscuous mode
+** 1 - turn on promiscuous mode
+**
+** =========================================================================
+*/
+#define BROADCAST_MODE_OFF 0
+#define BROADCAST_MODE_ON 1
+RC_RETURN
+RCSetBroadcastMode(U16 AdapterID, U16 Mode);
+/*
+** =========================================================================
+** RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+**
+** get broadcast mode setting
+**
+** Possible return values placed in pMode:
+** 0 = broadcast mode not set
+** 1 = broadcast mode is set
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+/*
+** =========================================================================
+** RCReportDriverCapability(U16 AdapterID, U32 capability)
+**
+** Currently defined bits:
+** WARM_REBOOT_CAPABLE 0x01
+**
+** =========================================================================
+*/
+RC_RETURN
+RCReportDriverCapability(U16 AdapterID, U32 capability);
+
+/*
+** RCGetFirmwareVer()
+**
+** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
+**
+** WARNING: user's space pointed to by pFirmString should be at least 60 bytes.
+*/
+RC_RETURN
+RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback);
+
+/*
+** ----------------------------------------------
+** LAN adapter Reset and Shutdown functions
+** ----------------------------------------------
+*/
+ /* resource flag bit assignments for RCResetLANCard() & RCShutdownLANCard() */
+#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS 0x0001
+#define RC_RESOURCE_RETURN_PEND_TX_BUFFERS 0x0002
+
+ /*
+ ** RCResetLANCard()
+ **
+ ** Reset LAN card operation. Causes a software reset of the ethernet
+ ** controller and restarts the command and receive units. Depending on
+ ** the ResourceFlags given, the buffers are either returned to the
+ ** host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and
+ ** detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
+ ** posted after issuing this) OR the buffers are kept and reused by
+ ** the ethernet controller. If CallbackFunction is not NULL, the function
+ ** will be called when the reset is complete. If the CallbackFunction is
+ ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset
+ ** to complete (please disable I2O interrupts during this method).
+ ** Any outstanding transmit or receive buffers that are complete will be
+ ** returned via the normal reply messages before the requested resource
+ ** buffers are returned.
+ ** A call to RCPostRecvBuffers() is needed to return the ethernet to full
+ ** operation if the receive buffers were returned during LANReset.
+ ** Note: The IOP status is not affected by a LAN reset.
+ */
+RC_RETURN RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+
+
+ /*
+ ** RCShutdownLANCard()
+ **
+ ** Shutdown LAN card operation and put into an idle (suspended) state.
+ ** The LAN card is restarted with RCResetLANCard() function.
+ ** Depending on the ResourceFlags given, the buffers are either returned
+ ** to the host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER
+ ** and detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
+ ** posted after issuing this) OR the buffers are kept and reused by
+ ** the ethernet controller. If CallbackFunction is not NULL, the function
+ ** will be called when the reset is complete. If the CallbackFunction is
+ ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset
+ ** to complete (please disable I2O interrupts during this method).
+ ** Any outstanding transmit or receive buffers that are complete will be
+ ** returned via the normal reply messages before the requested resource
+ ** buffers are returned.
+ ** Note: The IOP status is not affected by a LAN shutdown.
+ */
+RC_RETURN
+RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+
+ /*
+ ** RCResetIOP();
+ ** Initializes IOPState to I2O_IOP_STATE_RESET.
+ ** Stops access to outbound message Q.
+ ** Discards any outstanding transmit or posted receive buffers.
+ ** Clears outbound message Q.
+ */
+RC_RETURN
+RCResetIOP(U16 AdapterID);
+
+#endif /* RCLANMTL_H */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/rcmtl.c linux/drivers/net/rcmtl.c
--- v2.2.0-pre7/linux/drivers/net/rcmtl.c Tue Dec 22 14:16:56 1998
+++ linux/drivers/net/rcmtl.c Wed Dec 31 16:00:00 1969
@@ -1,2058 +0,0 @@
-/*
-** *************************************************************************
-**
-**
-** R C M T L . C $Revision: 1.1 $
-**
-**
-** RedCreek Message Transport Layer program module.
-**
-** ---------------------------------------------------------------------
-** --- Copyright (c) 1997-1998, RedCreek Communications Inc. ---
-** --- All rights reserved. ---
-** ---------------------------------------------------------------------
-**
-** File Description:
-**
-** Host side message transport layer.
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-***************************************************************************/
-
-#undef DEBUG
-
-#define RC_LINUX_MODULE
-#include "rcmtl.h"
-
-#define dprintf kprintf
-
-extern int printk(const char * fmt, ...);
-
- /* RedCreek LAN device Target ID */
-#define LAN_TARGET_ID 0x10
- /* RedCreek's OSM default LAN receive Initiator */
-#define DEFAULT_RECV_INIT_CONTEXT 0xA17
-
-
-/*
-** message structures
-*/
-
-#define TID_SZ 12
-#define FUNCTION_SZ 8
-
-/* Transaction Reply Lists (TRL) Control Word structure */
-
-#define TRL_SINGLE_FIXED_LENGTH 0x00
-#define TRL_SINGLE_VARIABLE_LENGTH 0x40
-#define TRL_MULTIPLE_FIXED_LENGTH 0x80
-
-/* LAN Class specific functions */
-
-#define LAN_PACKET_SEND 0x3B
-#define LAN_SDU_SEND 0x3D
-#define LAN_RECEIVE_POST 0x3E
-#define LAN_RESET 0x35
-#define LAN_SHUTDOWN 0x37
-
-/* Private Class specfic function */
-#define RC_PRIVATE 0xFF
-
-/* RC Executive Function Codes. */
-
-#define RC_CMD_ADAPTER_ASSIGN 0xB3
-#define RC_CMD_ADAPTER_READ 0xB2
-#define RC_CMD_ADAPTER_RELEASE 0xB5
-#define RC_CMD_BIOS_INFO_SET 0xA5
-#define RC_CMD_BOOT_DEVICE_SET 0xA7


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 07'
echo 'File patch-2.2.0-pre8 is continued in part 08'
echo 08 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part06

#!/bin/sh
# this is part 06 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 06; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

X break;
X default:
X printk("pcnet32: PCnet version %#x, no PCnet32 chip.\n",chip_version);
@@ -332,8 +352,14 @@
X dev->priv = lp;
X lp->name = chipname;
X lp->shared_irq = shared;
+ lp->full_duplex = full_duplex;
+ lp->options = options;
+
+ /* detect special T1/E1 WAN card by checking for MAC address */
+ if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75)
+ lp->options = PORT_FD | PORT_GPSI;
X
- lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
+ lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
X lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
X for (i = 0; i < 6; i++)
X lp->init_block.phys_addr[i] = dev->dev_addr[i];
@@ -382,11 +408,6 @@
X }
X }
X
- outw(0x0002, ioaddr+PCNET32_ADDR);
- /* only touch autoselect bit */
- outw(inw(ioaddr+PCNET32_BUS_IF) | 0x0002, ioaddr+PCNET32_BUS_IF);
-
-
X if (pcnet32_debug > 0)
X printk(version);
X
@@ -413,6 +434,7 @@
X {
X struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
X unsigned int ioaddr = dev->base_addr;
+ unsigned short val;
X int i;
X
X if (dev->irq == 0 ||
@@ -428,19 +450,40 @@
X outw(0x0014, ioaddr+PCNET32_ADDR);
X outw(0x0002, ioaddr+PCNET32_BUS_IF);
X
- /* Turn on auto-select of media (AUI, BNC). */
- outw(0x0002, ioaddr+PCNET32_ADDR);
- /* only touch autoselect bit */
- outw(inw(ioaddr+PCNET32_BUS_IF) | 0x0002, ioaddr+PCNET32_BUS_IF);
-
X if (pcnet32_debug > 1)
X printk("%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
X dev->name, dev->irq,
X (u32) virt_to_bus(lp->tx_ring),
X (u32) virt_to_bus(lp->rx_ring),
X (u32) virt_to_bus(&lp->init_block));
-
- lp->init_block.mode = 0x0000;
+
+ /* set/reset autoselect bit */
+ outw(0x0002, ioaddr+PCNET32_ADDR);
+ val = inw(ioaddr+PCNET32_BUS_IF) & ~2;
+ if (lp->options & PORT_ASEL)
+ val |= 2;
+ outw(val, ioaddr+PCNET32_BUS_IF);
+
+ /* handle full duplex setting */
+ if (lp->full_duplex) {
+ outw (0x0009, ioaddr+PCNET32_ADDR);
+ val = inw(ioaddr+PCNET32_BUS_IF) & ~3;
+ if (lp->options & PORT_FD) {
+ val |= 1;
+ if (lp->options == (PORT_FD | PORT_AUI))
+ val |= 2;
+ }
+ outw(val, ioaddr+PCNET32_BUS_IF);
+ }
+
+ /* set/reset GPSI bit in test register */
+ outw (0x007c, ioaddr+PCNET32_ADDR);
+ val = inw(ioaddr+PCNET32_DATA) & ~0x10;
+ if ((lp->options & PORT_PORTSEL) == PORT_GPSI)
+ val |= 0x10;
+ outw(val, ioaddr+PCNET32_DATA);
+
+ lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7);
X lp->init_block.filter[0] = 0x00000000;
X lp->init_block.filter[1] = 0x00000000;
X if (pcnet32_init_ring(dev))
@@ -515,7 +558,7 @@
X struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
X int i;
X
- lp->lock = 0, lp->tx_full = 0;
+ lp->tx_full = 0;
X lp->cur_rx = lp->cur_tx = 0;
X lp->dirty_rx = lp->dirty_tx = 0;
X
@@ -613,7 +656,6 @@
X outw(0x0000, ioaddr+PCNET32_ADDR);
X printk("%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", dev->name,
X inw(ioaddr+PCNET32_DATA));
- outw(0x0000, ioaddr+PCNET32_DATA);
X }
X
X /* Block a timer-based transmit from overlapping. This could better be
@@ -623,12 +665,8 @@


X return 1;
X }
X

- if (test_and_set_bit(0, (void*)&lp->lock) != 0) {
- if (pcnet32_debug > 0)
- printk("%s: tx queue lock!.\n", dev->name);
- /* don't clear dev->tbusy flag. */
- return 1;
- }
+ save_flags (flags);
+ cli ();
X
X /* Fill in a Tx ring entry */
X
@@ -655,15 +693,11 @@


X
X dev->trans_start = jiffies;

X
- save_flags(flags);
- cli();
- lp->lock = 0;
X if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
X clear_bit (0, (void *)&dev->tbusy);
X else
X lp->tx_full = 1;
X restore_flags(flags);
-


X return 0;
X }
X

@@ -675,6 +709,7 @@
X struct pcnet32_private *lp;
X unsigned int csr0, ioaddr;
X int boguscnt = max_interrupt_work;
+ int must_restart;
X
X if (dev == NULL) {
X printk ("pcnet32_interrupt(): irq %d for unknown device.\n", irq);
@@ -693,6 +728,8 @@
X /* Acknowledge all of the current interrupt sources ASAP. */
X outw(csr0 & ~0x004f, dev->base_addr + PCNET32_DATA);
X
+ must_restart = 0;
+
X if (pcnet32_debug > 5)
X printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n",
X dev->name, csr0, inw(dev->base_addr + PCNET32_DATA));
@@ -714,7 +751,7 @@
X
X if (status & 0x4000) {
X /* There was an major error, log it. */
- int err_status = le16_to_cpu(lp->tx_ring[entry].misc);
+ int err_status = le32_to_cpu(lp->tx_ring[entry].misc);
X lp->stats.tx_errors++;
X if (err_status & 0x04000000) lp->stats.tx_aborted_errors++;
X if (err_status & 0x08000000) lp->stats.tx_carrier_errors++;
@@ -725,10 +762,7 @@
X /* Remove this verbosity later! */
X printk("%s: Tx FIFO error! Status %4.4x.\n",
X dev->name, csr0);
- /* stop the chip to clear the error condition, then restart */
- outw(0x0000, dev->base_addr + PCNET32_ADDR);
- outw(0x0004, dev->base_addr + PCNET32_DATA);
- pcnet32_restart(dev, 0x0002);
+ must_restart = 1;
X }
X } else {
X if (status & 0x1800)
@@ -782,6 +816,13 @@
X dev->name, csr0);
X /* unlike for the lance, there is no restart needed */
X }
+
+ if (must_restart) {
+ /* stop the chip to clear the error condition, then restart */
+ outw(0x0000, dev->base_addr + PCNET32_ADDR);
+ outw(0x0004, dev->base_addr + PCNET32_DATA);
+ pcnet32_restart(dev, 0x0002);
+ }
X }
X
X /* Clear any other interrupt, and set interrupt enable. */
@@ -1014,9 +1055,9 @@
X if (dev->flags&IFF_PROMISC) {
X /* Log any net taps. */
X printk("%s: Promiscuous mode enabled.\n", dev->name);
- lp->init_block.mode = le16_to_cpu(0x8000);
+ lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PORT_PORTSEL) << 7);
X } else {
- lp->init_block.mode = 0x0000;
+ lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7);
X pcnet32_load_multicast (dev);
X }
X
@@ -1028,6 +1069,7 @@
X
X #ifdef MODULE
X MODULE_PARM(debug, "i");
+MODULE_PARM(options, "i");
X MODULE_PARM(max_interrupt_work, "i");
X MODULE_PARM(rx_copybreak, "i");
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.2.0-pre7/linux/drivers/net/ppp.c Tue Dec 22 14:16:56 1998
+++ linux/drivers/net/ppp.c Thu Jan 14 22:56:06 1999
@@ -4,7 +4,7 @@
X * Al Longyear <long...@netcom.com>
X * Extensively rewritten by Paul Mackerras <pau...@cs.anu.edu.au>
X *
- * ==FILEVERSION 981004==
+ * ==FILEVERSION 990114==
X *
X * NOTE TO MAINTAINERS:
X * If you modify this file at all, please set the number above to the
@@ -1216,6 +1216,7 @@
X } ppp_proto_type;
X
X static int rcv_proto_ip (struct ppp *, struct sk_buff *);
+static int rcv_proto_ipv6 (struct ppp *, struct sk_buff *);
X static int rcv_proto_ipx (struct ppp *, struct sk_buff *);
X static int rcv_proto_at (struct ppp *, struct sk_buff *);
X static int rcv_proto_vjc_comp (struct ppp *, struct sk_buff *);
@@ -1226,6 +1227,7 @@
X static
X ppp_proto_type proto_list[] = {
X { PPP_IP, rcv_proto_ip },
+ { PPP_IPV6, rcv_proto_ipv6 },
X { PPP_IPX, rcv_proto_ipx },
X { PPP_AT, rcv_proto_at },
X { PPP_VJC_COMP, rcv_proto_vjc_comp },
@@ -2003,6 +2005,19 @@
X }
X
X /*
+ * Process the receipt of an IPv6 frame
+ */
+static int
+rcv_proto_ipv6(struct ppp *ppp, struct sk_buff *skb)
+{
+ CHECK_PPP(0);
+ if ((ppp2dev(ppp)->flags & IFF_UP) && (skb->len > 0)
+ && ppp->sc_npmode[NP_IPV6] == NPMODE_PASS)
+ return ppp_rcv_rx(ppp, ETH_P_IPV6, skb);


+ return 0;
+}
+

+/*
X * Process the receipt of an IPX frame
X */
X static int
@@ -2382,6 +2397,10 @@
X case ETH_P_IP:
X proto = PPP_IP;
X npmode = ppp->sc_npmode[NP_IP];
+ break;
+ case ETH_P_IPV6:
+ proto = PPP_IPV6;
+ npmode = ppp->sc_npmode[NP_IPV6];
X break;
X case ETH_P_IPX:
X proto = PPP_IPX;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/rcif.h linux/drivers/net/rcif.h
--- v2.2.0-pre7/linux/drivers/net/rcif.h Tue Dec 22 14:16:56 1998
+++ linux/drivers/net/rcif.h Thu Jan 14 22:58:47 1999
@@ -8,7 +8,7 @@
X ** RedCreek InterFace include file.
X **
X ** ---------------------------------------------------------------------
-** --- Copyright (c) 1998, RedCreek Communications Inc. ---
+** --- Copyright (c) 1998-1999, RedCreek Communications Inc. ---
X ** --- All rights reserved. ---
X ** ---------------------------------------------------------------------
X **
@@ -38,7 +38,7 @@
X
X /* The following protocol revision # should be incremented every time
X a new protocol or new structures are used in this file. */
-int USER_PROTOCOL_REV = 1; /* used to track different protocol revisions */
+int USER_PROTOCOL_REV = 2; /* used to track different protocol revisions */
X
X /* define a single TCB & buffer */
X typedef struct /* a single buffer */
@@ -124,6 +124,31 @@
X U32 LinkSpeedCode;
X } RCgetspeed; /* <---- RCgetspeed */
X
+ /* SETSPEED structure */
+ struct RCsetspeed_tag {
+ U16 LinkSpeedCode;
+ } RCsetspeed; /* <---- RCsetspeed */
+
+ /* GETPROM structure */
+ struct RCgetprom_tag {
+ U32 PromMode;
+ } RCgetprom; /* <---- RCgetprom */
+
+ /* SETPROM structure */
+ struct RCsetprom_tag {
+ U16 PromMode;
+ } RCsetprom; /* <---- RCsetprom */
+
+ /* GETBROADCAST structure */
+ struct RCgetbroadcast_tag {
+ U32 BroadcastMode;
+ } RCgetbroadcast; /* <---- RCgetbroadcast */
+
+ /* SETBROADCAST structure */
+ struct RCsetbroadcast_tag {
+ U16 BroadcastMode;
+ } RCsetbroadcast; /* <---- RCsetbroadcast */
+
X /* GETFIRMWAREVER structure */
X #define FirmStringLen 80
X struct RCgetfwver_tag {
@@ -136,12 +161,23 @@
X U32 NetMask;
X } RCgetipandmask; /* <---- RCgetipandmask */
X
+ /* SETIPANDMASK structure */
+ struct RCsetipnmask_tag {
+ U32 IpAddr;
+ U32 NetMask;
+ } RCsetipandmask; /* <---- RCsetipandmask */
+
X /* GETMAC structure */
X #define MAC_SIZE 10
X struct RCgetmac_tag {
X U8 mac[MAC_SIZE];
X } RCgetmac; /* <---- RCgetmac */
X
+ /* SETMAC structure */
+ struct RCsetmac_tag {
+ U8 mac[MAC_SIZE];
+ } RCsetmac; /* <---- RCsetmac */
+
X /* GETLINKSTATUS structure */
X struct RCgetlnkstatus_tag {
X U32 ReturnStatus;
@@ -166,35 +202,56 @@
X union RC_user_data_tag { /* structure tags used are taken from RC_user_tag structure above */
X struct RCgetinfo_tag *getinfo;
X struct RCgetspeed_tag *getspeed;
+ struct RCgetprom_tag *getprom;
+ struct RCgetbroadcast_tag *getbroadcast;
X struct RCgetfwver_tag *getfwver;
X struct RCgetipnmask_tag *getipandmask;
X struct RCgetmac_tag *getmac;
X struct RCgetlnkstatus_tag *getlinkstatus;
X struct RCgetlinkstats_tag *getlinkstatistics;
X struct RCdefault_tag *rcdefault;
+ struct RCsetspeed_tag *setspeed;
+ struct RCsetprom_tag *setprom;
+ struct RCsetbroadcast_tag *setbroadcast;
+ struct RCsetipnmask_tag *setipandmask;
+ struct RCsetmac_tag *setmac;
X } _RC_user_data; /* declare as a global, so the defines below will work */
X
X /* 3) Structure short-cut entry */
X /* define structure short-cuts */ /* structure names are taken from RC_user_tag structure above */
X #define RCUS_GETINFO data.RCgetinfo;
X #define RCUS_GETSPEED data.RCgetspeed;
+#define RCUS_GETPROM data.RCgetprom;
+#define RCUS_GETBROADCAST data.RCgetbroadcast;
X #define RCUS_GETFWVER data.RCgetfwver;
X #define RCUS_GETIPANDMASK data.RCgetipandmask;
X #define RCUS_GETMAC data.RCgetmac;
X #define RCUS_GETLINKSTATUS data.RCgetlnkstatus;
X #define RCUS_GETLINKSTATISTICS data.RCgetlinkstats;
X #define RCUS_DEFAULT data.RCdefault;
+#define RCUS_SETSPEED data.RCsetspeed;
+#define RCUS_SETPROM data.RCsetprom;
+#define RCUS_SETBROADCAST data.RCsetbroadcast;
+#define RCUS_SETIPANDMASK data.RCsetipandmask;
+#define RCUS_SETMAC data.RCsetmac;
X
X /* 4) Data short-cut entry */
X /* define data short-cuts */ /* pointer names are from RC_user_data_tag union (just below RC_user_tag) */
X #define RCUD_GETINFO _RC_user_data.getinfo
X #define RCUD_GETSPEED _RC_user_data.getspeed
+#define RCUD_GETPROM _RC_user_data.getprom
+#define RCUD_GETBROADCAST _RC_user_data.getbroadcast
X #define RCUD_GETFWVER _RC_user_data.getfwver
X #define RCUD_GETIPANDMASK _RC_user_data.getipandmask
X #define RCUD_GETMAC _RC_user_data.getmac
X #define RCUD_GETLINKSTATUS _RC_user_data.getlinkstatus
X #define RCUD_GETLINKSTATISTICS _RC_user_data.getlinkstatistics
X #define RCUD_DEFAULT _RC_user_data.rcdefault
+#define RCUD_SETSPEED _RC_user_data.setspeed
+#define RCUD_SETPROM _RC_user_data.setprom
+#define RCUD_SETBROADCAST _RC_user_data.setbroadcast
+#define RCUD_SETIPANDMASK _RC_user_data.setipandmask
+#define RCUD_SETMAC _RC_user_data.setmac
X
X /* 5) Command identifier entry */
X /* define command identifiers */
@@ -205,7 +262,14 @@
X #define RCUC_GETMAC 0x05
X #define RCUC_GETLINKSTATUS 0x06
X #define RCUC_GETLINKSTATISTICS 0x07
+#define RCUC_GETPROM 0x14
+#define RCUC_GETBROADCAST 0x15
X #define RCUC_DEFAULT 0xff
+#define RCUC_SETSPEED 0x08
+#define RCUC_SETIPANDMASK 0x09
+#define RCUC_SETMAC 0x0a
+#define RCUC_SETPROM 0x16
+#define RCUC_SETBROADCAST 0x17
X
X /* define ioctl commands to use, when talking to RC 45/PCI driver */
X #define RCU_PROTOCOL_REV SIOCDEVPRIVATE
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/rclanmtl.c linux/drivers/net/rclanmtl.c
--- v2.2.0-pre7/linux/drivers/net/rclanmtl.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/rclanmtl.c Thu Jan 14 22:58:47 1999
@@ -0,0 +1,2307 @@


+/*
+** *************************************************************************
+**
+**

+** R C L A N M T L . C $Revision: 5 $
+**
+**
+** RedCreek I2O LAN Message Transport Layer program module.


+**
+** ---------------------------------------------------------------------
+** --- Copyright (c) 1997-1999, RedCreek Communications Inc. ---
+** --- All rights reserved. ---
+** ---------------------------------------------------------------------
+**
+** File Description:
+**

+** Host side I2O (Intelligent I/O) LAN message transport layer.


+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

+** *************************************************************************
+*/
+
+#undef DEBUG
+
+#define RC_LINUX_MODULE
+#include "rclanmtl.h"
+
+#define dprintf kprintf
+
+extern int printk(const char * fmt, ...);
+
+ /* RedCreek LAN device Target ID */
+#define RC_LAN_TARGET_ID 0x10
+ /* RedCreek's OSM default LAN receive Initiator */
+#define DEFAULT_RECV_INIT_CONTEXT 0xA17
+
+
+/*
+** I2O message structures
+*/
+
+#define I2O_TID_SZ 12
+#define I2O_FUNCTION_SZ 8
+
+/* Transaction Reply Lists (TRL) Control Word structure */
+
+#define I2O_TRL_FLAGS_SINGLE_FIXED_LENGTH 0x00
+#define I2O_TRL_FLAGS_SINGLE_VARIABLE_LENGTH 0x40
+#define I2O_TRL_FLAGS_MULTIPLE_FIXED_LENGTH 0x80
+
+/* LAN Class specific functions */
+
+#define I2O_LAN_PACKET_SEND 0x3B
+#define I2O_LAN_SDU_SEND 0x3D
+#define I2O_LAN_RECEIVE_POST 0x3E
+#define I2O_LAN_RESET 0x35
+#define I2O_LAN_SHUTDOWN 0x37
+
+/* Private Class specfic function */
+#define I2O_PRIVATE 0xFF
+
+/* I2O Executive Function Codes. */
+
+#define I2O_EXEC_ADAPTER_ASSIGN 0xB3
+#define I2O_EXEC_ADAPTER_READ 0xB2
+#define I2O_EXEC_ADAPTER_RELEASE 0xB5
+#define I2O_EXEC_BIOS_INFO_SET 0xA5
+#define I2O_EXEC_BOOT_DEVICE_SET 0xA7
+#define I2O_EXEC_CONFIG_VALIDATE 0xBB
+#define I2O_EXEC_CONN_SETUP 0xCA
+#define I2O_EXEC_DEVICE_ASSIGN 0xB7
+#define I2O_EXEC_DEVICE_RELEASE 0xB9
+#define I2O_EXEC_HRT_GET 0xA8
+#define I2O_EXEC_IOP_CLEAR 0xBE
+#define I2O_EXEC_IOP_CONNECT 0xC9
+#define I2O_EXEC_IOP_RESET 0xBD
+#define I2O_EXEC_LCT_NOTIFY 0xA2
+#define I2O_EXEC_OUTBOUND_INIT 0xA1
+#define I2O_EXEC_PATH_ENABLE 0xD3
+#define I2O_EXEC_PATH_QUIESCE 0xC5
+#define I2O_EXEC_PATH_RESET 0xD7
+#define I2O_EXEC_STATIC_MF_CREATE 0xDD
+#define I2O_EXEC_STATIC_MF_RELEASE 0xDF
+#define I2O_EXEC_STATUS_GET 0xA0
+#define I2O_EXEC_SW_DOWNLOAD 0xA9
+#define I2O_EXEC_SW_UPLOAD 0xAB
+#define I2O_EXEC_SW_REMOVE 0xAD
+#define I2O_EXEC_SYS_ENABLE 0xD1
+#define I2O_EXEC_SYS_MODIFY 0xC1
+#define I2O_EXEC_SYS_QUIESCE 0xC3
+#define I2O_EXEC_SYS_TAB_SET 0xA3
+
+
+ /* Init Outbound Q status */
+#define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01
+#define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02
+#define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03
+#define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04
+
+
+#define I2O_UTIL_NOP 0x00
+
+
+/* I2O Get Status State values */
+
+#define I2O_IOP_STATE_INITIALIZING 0x01
+#define I2O_IOP_STATE_RESET 0x02
+#define I2O_IOP_STATE_HOLD 0x04
+#define I2O_IOP_STATE_READY 0x05
+#define I2O_IOP_STATE_OPERATIONAL 0x08
+#define I2O_IOP_STATE_FAILED 0x10
+#define I2O_IOP_STATE_FAULTED 0x11
+
+
+/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */
+
+#define I2O_REPLY_STATUS_SUCCESS 0x00
+#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
+#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
+#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
+#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
+#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
+#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x07
+#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x08
+#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x09
+#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0A
+#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80
+
+
+/* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes.*/
+
+#define I2O_DETAIL_STATUS_SUCCESS 0x0000
+#define I2O_DETAIL_STATUS_BAD_KEY 0x0001
+#define I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE 0x0002
+#define I2O_DETAIL_STATUS_DEVICE_BUSY 0x0003
+#define I2O_DETAIL_STATUS_DEVICE_LOCKED 0x0004
+#define I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE 0x0005
+#define I2O_DETAIL_STATUS_DEVICE_RESET 0x0006
+#define I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION 0x0007
+#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD 0x0008
+#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT 0x0009
+#define I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS 0x000A
+#define I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS 0x000B
+#define I2O_DETAIL_STATUS_INVALID_OFFSET 0x000C
+#define I2O_DETAIL_STATUS_INVALID_PARAMETER 0x000D
+#define I2O_DETAIL_STATUS_INVALID_REQUEST 0x000E
+#define I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS 0x000F
+#define I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE 0x0010
+#define I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL 0x0011
+#define I2O_DETAIL_STATUS_MISSING_PARAMETER 0x0012
+#define I2O_DETAIL_STATUS_NO_SUCH_PAGE 0x0013
+#define I2O_DETAIL_STATUS_REPLY_BUFFER_FULL 0x0014
+#define I2O_DETAIL_STATUS_TCL_ERROR 0x0015
+#define I2O_DETAIL_STATUS_TIMEOUT 0x0016
+#define I2O_DETAIL_STATUS_UNKNOWN_ERROR 0x0017
+#define I2O_DETAIL_STATUS_UNKNOWN_FUNCTION 0x0018
+#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x0019
+#define I2O_DETAIL_STATUS_UNSUPPORTED_VERSION 0x001A
+
+ /* I2O msg header defines for VersionOffset */
+#define I2OMSGVER_1_5 0x0001
+#define SGL_OFFSET_0 I2OMSGVER_1_5
+#define SGL_OFFSET_4 (0x0040 | I2OMSGVER_1_5)
+#define TRL_OFFSET_5 (0x0050 | I2OMSGVER_1_5)
+#define TRL_OFFSET_6 (0x0060 | I2OMSGVER_1_5)
+
+ /* I2O msg header defines for MsgFlags */
+#define MSG_STATIC 0x0100
+#define MSG_64BIT_CNTXT 0x0200
+#define MSG_MULTI_TRANS 0x1000
+#define MSG_FAIL 0x2000
+#define MSG_LAST 0x4000
+#define MSG_REPLY 0x8000
+
+ /* normal LAN request message MsgFlags and VersionOffset (0x1041) */
+#define LAN_MSG_REQST (MSG_MULTI_TRANS | SGL_OFFSET_4)
+
+ /* minimum size msg */
+#define THREE_WORD_MSG_SIZE 0x00030000
+#define FOUR_WORD_MSG_SIZE 0x00040000
+#define FIVE_WORD_MSG_SIZE 0x00050000
+#define SIX_WORD_MSG_SIZE 0x00060000
+#define SEVEN_WORD_MSG_SIZE 0x00070000
+#define EIGHT_WORD_MSG_SIZE 0x00080000
+#define NINE_WORD_MSG_SIZE 0x00090000
+
+/* Special TID Assignments */
+
+#define I2O_IOP_TID 0
+#define I2O_HOST_TID 1
+
+ /* RedCreek I2O private message codes */
+#define RC_PRIVATE_GET_MAC_ADDR 0x0001/**/ /* OBSOLETE */
+#define RC_PRIVATE_SET_MAC_ADDR 0x0002
+#define RC_PRIVATE_GET_NIC_STATS 0x0003
+#define RC_PRIVATE_GET_LINK_STATUS 0x0004
+#define RC_PRIVATE_SET_LINK_SPEED 0x0005
+#define RC_PRIVATE_SET_IP_AND_MASK 0x0006
+/* #define RC_PRIVATE_GET_IP_AND_MASK 0x0007 */ /* OBSOLETE */
+#define RC_PRIVATE_GET_LINK_SPEED 0x0008
+#define RC_PRIVATE_GET_FIRMWARE_REV 0x0009
+/* #define RC_PRIVATE_GET_MAC_ADDR 0x000A *//**/
+#define RC_PRIVATE_GET_IP_AND_MASK 0x000B /**/
+#define RC_PRIVATE_DEBUG_MSG 0x000C
+#define RC_PRIVATE_REPORT_DRIVER_CAPABILITY 0x000D
+#define RC_PRIVATE_SET_PROMISCUOUS_MODE 0x000e
+#define RC_PRIVATE_GET_PROMISCUOUS_MODE 0x000f
+#define RC_PRIVATE_SET_BROADCAST_MODE 0x0010
+#define RC_PRIVATE_GET_BROADCAST_MODE 0x0011
+
+#define RC_PRIVATE_REBOOT 0x00FF
+
+
+/* I2O message header */
+typedef struct _I2O_MESSAGE_FRAME
+{
+ U8 VersionOffset;
+ U8 MsgFlags;
+ U16 MessageSize;
+ BF TargetAddress:I2O_TID_SZ;
+ BF InitiatorAddress:I2O_TID_SZ;
+ BF Function:I2O_FUNCTION_SZ;
+ U32 InitiatorContext;
+ /* SGL[] */
+}
+I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME;
+
+
+ /* assumed a 16K minus 256 byte space for outbound queue message frames */
+#define MSG_FRAME_SIZE 512
+#define NMBR_MSG_FRAMES 30
+
+/*
+** Message Unit CSR definitions for RedCreek PCI45 board
+*/
+typedef struct tag_rcatu
+{
+ volatile unsigned long APICRegSel; /* APIC Register Select */
+ volatile unsigned long reserved0;
+ volatile unsigned long APICWinReg; /* APIC Window Register */
+ volatile unsigned long reserved1;
+ volatile unsigned long InMsgReg0; /* inbound message register 0 */
+ volatile unsigned long InMsgReg1; /* inbound message register 1 */
+ volatile unsigned long OutMsgReg0; /* outbound message register 0 */
+ volatile unsigned long OutMsgReg1; /* outbound message register 1 */
+ volatile unsigned long InDoorReg; /* inbound doorbell register */
+ volatile unsigned long InIntStat; /* inbound interrupt status register */
+ volatile unsigned long InIntMask; /* inbound interrupt mask register */
+ volatile unsigned long OutDoorReg; /* outbound doorbell register */
+ volatile unsigned long OutIntStat; /* outbound interrupt status register */
+ volatile unsigned long OutIntMask; /* outbound interrupt mask register */
+ volatile unsigned long reserved2;
+ volatile unsigned long reserved3;
+ volatile unsigned long InQueue; /* inbound queue port */
+ volatile unsigned long OutQueue; /* outbound queue port */
+ volatile unsigned long reserved4;
+ volatile unsigned long reserver5;
+ /* RedCreek extension */
+ volatile unsigned long EtherMacLow;
+ volatile unsigned long EtherMacHi;
+ volatile unsigned long IPaddr;
+ volatile unsigned long IPmask;
+}
+ATU, *PATU;
+
+ /*
+ ** typedef PAB
+ **
+ ** PCI Adapter Block - holds instance specific information and is located
+ ** in a reserved space at the start of the message buffer allocated by user.
+ */
+typedef struct
+{
+ PATU p_atu; /* ptr to ATU register block */
+ PU8 pPci45LinBaseAddr;
+ PU8 pLinOutMsgBlock;
+ U32 outMsgBlockPhyAddr;
+ PFNTXCALLBACK pTransCallbackFunc;
+ PFNRXCALLBACK pRecvCallbackFunc;
+ PFNCALLBACK pRebootCallbackFunc;
+ PFNCALLBACK pCallbackFunc;
+ U16 IOPState;
+ U16 InboundMFrameSize;
+}
+PAB, *PPAB;
+
+ /*
+ ** in reserved space right after PAB in host memory is area for returning
+ ** values from card
+ */
+
+ /*
+ ** Array of pointers to PCI Adapter Blocks.
+ ** Indexed by a zero based (0-31) interface number.
+ */
+#define MAX_ADAPTERS 32
+static PPAB PCIAdapterBlock[MAX_ADAPTERS] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+
+/*
+** typedef NICSTAT
+**
+** Data structure for NIC statistics retruned from PCI card. Data copied from
+** here to user allocated RCLINKSTATS (see rclanmtl.h) structure.
+*/
+typedef struct tag_NicStat
+{
+ unsigned long TX_good;
+ unsigned long TX_maxcol;
+ unsigned long TX_latecol;
+ unsigned long TX_urun;
+ unsigned long TX_crs; /* lost carrier sense */
+ unsigned long TX_def; /* transmit deferred */
+ unsigned long TX_singlecol; /* single collisions */
+ unsigned long TX_multcol;
+ unsigned long TX_totcol;
+ unsigned long Rcv_good;
+ unsigned long Rcv_CRCerr;
+ unsigned long Rcv_alignerr;
+ unsigned long Rcv_reserr; /* rnr'd pkts */
+ unsigned long Rcv_orun;
+ unsigned long Rcv_cdt;
+ unsigned long Rcv_runt;
+ unsigned long dump_status; /* last field directly from the chip */
+}
+NICSTAT, *P_NICSTAT;
+
+
+#define DUMP_DONE 0x0000A005 /* completed statistical dump */
+#define DUMP_CLEAR 0x0000A007 /* completed stat dump and clear counters */
+
+
+static volatile int msgFlag;
+
+
+/* local function prototypes */
+static void ProcessOutboundI2OMsg(PPAB pPab, U32 phyMsgAddr);
+static int FillI2OMsgSGLFromTCB(PU32 pMsg, PRCTCB pXmitCntrlBlock);
+static int GetI2OStatus(PPAB pPab);
+static int SendI2OOutboundQInitMsg(PPAB pPab);
+static int SendEnableSysMsg(PPAB pPab);
+
+
+/* 1st 100h bytes of message block is reserved for messenger instance */
+#define ADAPTER_BLOCK_RESERVED_SPACE 0x100
+
+/*
+** =========================================================================
+** RCInitI2OMsgLayer()
+**
+** Initialize the RedCreek I2O Module and adapter.
+**
+** Inputs: AdapterID - interface number from 0 to 15
+** pciBaseAddr - virual base address of PCI (set by BIOS)
+** p_msgbuf - virual address to private message block (min. 16K)
+** p_phymsgbuf - physical address of private message block
+** TransmitCallbackFunction - address of transmit callback function
+** ReceiveCallbackFunction - address of receive callback function
+**
+** private message block is allocated by user. It must be in locked pages.
+** p_msgbuf and p_phymsgbuf point to the same location. Must be contigous
+** memory block of a minimum of 16K byte and long word aligned.
+** =========================================================================
+*/
+RC_RETURN
+RCInitI2OMsgLayer(U16 AdapterID, U32 pciBaseAddr,

+ PU8 p_msgbuf, PU8 p_phymsgbuf,
+ PFNTXCALLBACK TransmitCallbackFunction,
+ PFNRXCALLBACK ReceiveCallbackFunction,
+ PFNCALLBACK RebootCallbackFunction)
+{

+ int result;
+ PPAB pPab;
+
+#ifdef DEBUG
+ kprintf("InitI2O: Adapter:0x%04.4ux ATU:0x%08.8ulx msgbuf:0x%08.8ulx phymsgbuf:0x%08.8ulx\n"
+ "TransmitCallbackFunction:0x%08.8ulx ReceiveCallbackFunction:0x%08.8ulx\n",
+ AdapterID, pciBaseAddr, p_msgbuf, p_phymsgbuf, TransmitCallbackFunction, ReceiveCallbackFunction);


+#endif /* DEBUG */
+
+

+ /* Check if this interface already initialized - if so, shut it down */
+ if (PCIAdapterBlock[AdapterID] != NULL)
+ {
+ printk("PCIAdapterBlock[%d]!=NULL\n", AdapterID);
+// RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+ PCIAdapterBlock[AdapterID] = NULL;
+ }
+
+ /*
+ ** store adapter instance values in adapter block.
+ ** Adapter block is at beginning of message buffer
+ */
+ pPab = (PPAB)p_msgbuf;
+
+ pPab->p_atu = (PATU)pciBaseAddr;
+ pPab->pPci45LinBaseAddr = (PU8)pciBaseAddr;
+
+ /* Set outbound message frame addr - skip over Adapter Block */
+ pPab->outMsgBlockPhyAddr = (U32)(p_phymsgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+ pPab->pLinOutMsgBlock = (PU8)(p_msgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+
+ /* store callback function addresses */
+ pPab->pTransCallbackFunc = TransmitCallbackFunction;
+ pPab->pRecvCallbackFunc = ReceiveCallbackFunction;
+ pPab->pRebootCallbackFunc = RebootCallbackFunction;
+ pPab->pCallbackFunc = (PFNCALLBACK)NULL;
+
+ /*
+ ** Initialize I2O IOP
+ */
+ result = GetI2OStatus(pPab);
+
+ if (result != RC_RTN_NO_ERROR)
+ return result;
+
+ if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL)
+ {
+ printk("pPab->IOPState == op: resetting adapter\n");
+ RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+ }
+
+ result = SendI2OOutboundQInitMsg(pPab);
+
+ if (result != RC_RTN_NO_ERROR)
+ return result;
+
+ result = SendEnableSysMsg(pPab);
+
+ if (result != RC_RTN_NO_ERROR)
+ return result;
+
+ PCIAdapterBlock[AdapterID] = pPab;


+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================

+** Disable and Enable I2O interrupts. I2O interrupts are enabled at Init time
+** but can be disabled and re-enabled through these two function calls.
+** Packets will still be put into any posted received buffers and packets will
+** be sent through RCI2OSendPacket() functions. Disabling I2O interrupts
+** will prevent hardware interrupt to host even though the outbound I2O msg


+** queue is not emtpy.

+** =========================================================================
+*/
+#define i960_OUT_POST_Q_INT_BIT 0x0008 /* bit set masks interrupts */
+
+RC_RETURN RCDisableI2OInterrupts(U16 AdapterID)
+{
+ PPAB pPab;
+


+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+

+ pPab->p_atu->OutIntMask |= i960_OUT_POST_Q_INT_BIT;


+
+ return RC_RTN_NO_ERROR;
+}
+

+RC_RETURN RCEnableI2OInterrupts(U16 AdapterID)
+{


+ PPAB pPab;
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+

+ pPab->p_atu->OutIntMask &= ~i960_OUT_POST_Q_INT_BIT;


+
+ return RC_RTN_NO_ERROR;
+
+}
+

+
+/*
+** =========================================================================
+** RCI2OSendPacket()
+** =========================================================================
+*/
+RC_RETURN
+RCI2OSendPacket(U16 AdapterID, U32 InitiatorContext, PRCTCB pTransCtrlBlock)
+{
+ U32 msgOffset;
+ PU32 pMsg;
+ int size;
+ PPAB pPab;
+
+#ifdef DEBUG
+ kprintf("RCI2OSendPacket()...\n");


+#endif /* DEBUG */
+

+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+

+ /* get Inbound free Q entry - reading from In Q gets free Q entry */
+ /* offset to Msg Frame in PCI msg block */


+
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG

+ kprintf("RCI2OSendPacket(): Inbound Free Q empty!\n");


+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+

+ size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
+
+ if (size == -1) /* error processing TCB - send NOP msg */
+ {
+#ifdef DEBUG
+ kprintf("RCI2OSendPacket(): Error Rrocess TCB!\n");
+#endif /* DEBUG */
+ pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ return RC_RTN_TCB_ERROR;
+ }
+ else /* send over msg header */
+ {
+ pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
+ pMsg[1] = I2O_LAN_PACKET_SEND << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = InitiatorContext;
+ pMsg[3] = 0; /* batch reply */


+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;

+ return RC_RTN_NO_ERROR;
+ }
+}
+

+
+/*
+** =========================================================================
+** RCI2OPostRecvBuffer()
+**
+** inputs: pBufrCntrlBlock - pointer to buffer control block
+**
+** returns TRUE if successful in sending message, else FALSE.
+** =========================================================================
+*/
+RC_RETURN
+RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransCtrlBlock)
+{
+ U32 msgOffset;
+ PU32 pMsg;
+ int size;
+ PPAB pPab;
+
+#ifdef DEBUG
+ kprintf("RCPostRecvBuffers()...\n");


+#endif /* DEBUG */
+

+ /* search for DeviceHandle */


+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+

+ /* get Inbound free Q entry - reading from In Q gets free Q entry */
+ /* offset to Msg Frame in PCI msg block */


+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG

+ kprintf("RCPostRecvBuffers(): Inbound Free Q empty!\n");


+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+
+ }
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+

+ size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
+
+ if (size == -1) /* error prcessing TCB - send 3 DWORD private msg == NOP */
+ {
+#ifdef DEBUG
+ kprintf("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", size);
+#endif /* DEBUG */
+ pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ /* post to Post Q */

+ pPab->p_atu->InQueue = msgOffset;

+ return RC_RTN_TCB_ERROR;
+ }
+ else /* send over size msg header */
+ {
+ pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
+ pMsg[1] = I2O_LAN_RECEIVE_POST << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;


+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;

+ pMsg[3] = *(PU32)pTransCtrlBlock; /* number of packet buffers */
+ /* post to Post Q */

+ pPab->p_atu->InQueue = msgOffset;

+ return RC_RTN_NO_ERROR;
+ }
+}
+

+
+/*
+** =========================================================================
+** RCProcI2OMsgQ()
+**
+** Process I2O outbound message queue until empty.
+** =========================================================================
+*/
+void
+RCProcI2OMsgQ(U16 AdapterID)
+{
+ U32 phyAddrMsg;


+ PU8 p8Msg;
+ PU32 p32;

+ U16 count;
+ PPAB pPab;
+ unsigned char debug_msg[20];


+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)

+ return;
+
+ phyAddrMsg = pPab->p_atu->OutQueue;
+
+ while (phyAddrMsg != 0xFFFFFFFF)


+ {
+ p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
+ p32 = (PU32)p8Msg;
+

+ //printk(" msg: 0x%x 0x%x \n", p8Msg[7], p32[5]);
+
+ /*
+ ** Send Packet Reply Msg
+ */
+ if (I2O_LAN_PACKET_SEND == p8Msg[7]) /* function code byte */
+ {
+ count = *(PU16)(p8Msg+2);
+ count -= p8Msg[0] >> 4;
+ /* status, count, context[], adapter */
+ (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, AdapterID);
+ }
+ /*
+ ** Receive Packet Reply Msg */
+ else if (I2O_LAN_RECEIVE_POST == p8Msg[7])
+ {
+#ifdef DEBUG
+ kprintf("I2O_RECV_REPLY pPab:0x%08.8ulx p8Msg:0x%08.8ulx p32:0x%08.8ulx\n", pPab, p8Msg, p32);


+ kprintf("msg: 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",

+ p32[0], p32[1], p32[2], p32[3]);


+ kprintf(" 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",

+ p32[4], p32[5], p32[6], p32[7]);
+ kprintf(" 0x%08.8ulx:0X%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+ p32[8], p32[9], p32[10], p32[11]);
+#endif
+ /* status, count, buckets remaining, packetParmBlock, adapter */
+ (*pPab->pRecvCallbackFunc)(p8Msg[19], p8Msg[12], p32[5], p32+6, AdapterID);
+
+
+ }
+ else if (I2O_LAN_RESET == p8Msg[7] || I2O_LAN_SHUTDOWN == p8Msg[7])
+ {
+ if (pPab->pCallbackFunc)
+ {
+ (*pPab->pCallbackFunc)(p8Msg[19],0,0,AdapterID);
+ }
+ else
+ {
+ pPab->pCallbackFunc = (PFNCALLBACK) 1;
+ }
+ //PCIAdapterBlock[AdapterID] = 0;
+ }
+ else if (I2O_PRIVATE == p8Msg[7])
+ {
+ //printk("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]);
+ switch (p32[5])
+ {
+ case RC_PRIVATE_DEBUG_MSG:
+ msgFlag = 1;
+ /*printk("Received I2O_PRIVATE msg\n");*/
+ debug_msg[15] = (p32[6]&0xff000000) >> 24;
+ debug_msg[14] = (p32[6]&0x00ff0000) >> 16;
+ debug_msg[13] = (p32[6]&0x0000ff00) >> 8;
+ debug_msg[12] = (p32[6]&0x000000ff);
+
+ debug_msg[11] = (p32[7]&0xff000000) >> 24;
+ debug_msg[10] = (p32[7]&0x00ff0000) >> 16;
+ debug_msg[ 9] = (p32[7]&0x0000ff00) >> 8;
+ debug_msg[ 8] = (p32[7]&0x000000ff);
+
+ debug_msg[ 7] = (p32[8]&0xff000000) >> 24;
+ debug_msg[ 6] = (p32[8]&0x00ff0000) >> 16;
+ debug_msg[ 5] = (p32[8]&0x0000ff00) >> 8;
+ debug_msg[ 4] = (p32[8]&0x000000ff);
+
+ debug_msg[ 3] = (p32[9]&0xff000000) >> 24;
+ debug_msg[ 2] = (p32[9]&0x00ff0000) >> 16;
+ debug_msg[ 1] = (p32[9]&0x0000ff00) >> 8;
+ debug_msg[ 0] = (p32[9]&0x000000ff);
+
+ debug_msg[16] = '\0';
+ printk (debug_msg);
+ break;
+ case RC_PRIVATE_REBOOT:
+ printk("Adapter reboot initiated...\n");
+ if (pPab->pRebootCallbackFunc)
+ {
+ (*pPab->pRebootCallbackFunc)(0,0,0,AdapterID);
+ }
+ break;
+ default:
+ printk("Unknown private I2O msg received: 0x%x\n",
+ p32[5]);


+ break;
+ }
+ }
+

+ /*
+ ** Process other Msg's
+ */
+ else
+ {
+ ProcessOutboundI2OMsg(pPab, phyAddrMsg);
+ }
+
+ /* return MFA to outbound free Q*/
+ pPab->p_atu->OutQueue = phyAddrMsg;
+
+ /* any more msgs? */
+ phyAddrMsg = pPab->p_atu->OutQueue;
+ }


+}
+
+
+/*
+** =========================================================================

+** Returns LAN interface statistical counters to space provided by caller at
+** StatsReturnAddr. Returns 0 if success, else RC_RETURN code.
+** This function will call the WaitCallback function provided by
+** user while waiting for card to respond.
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkStatistics(U16 AdapterID,

+ P_RCLINKSTATS StatsReturnAddr,
+ PFNWAITCALLBACK WaitCallback)
+{

+ U32 msgOffset;
+ volatile U32 timeout;
+ volatile PU32 pMsg;
+ volatile PU32 p32, pReturnAddr;
+ P_NICSTAT pStats;
+ int i;
+ PPAB pPab;
+
+/*kprintf("Get82558Stats() StatsReturnAddr:0x%08.8ulx\n", StatsReturnAddr);*/


+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+

+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG

+ kprintf("Get8255XStats(): Inbound Free Q empty!\n");
+#endif


+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+

+/*dprintf("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintf("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
+


+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;

+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;

+ pMsg[3] = 0x112; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS;


+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+

+ p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+

+ pStats = (P_NICSTAT)p32;
+ pStats->dump_status = 0xFFFFFFFF;


+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+

+ timeout = 100000;
+ while (1)


+ {
+ if (WaitCallback)
+ (*WaitCallback)();
+

+ for (i = 0; i < 1000; i++)
+ ;
+

+ if (pStats->dump_status != 0xFFFFFFFF)


+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG

+ kprintf("RCGet82558Stats() Timeout waiting for NIC statistics\n");
+#endif


+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+

+ pReturnAddr = (PU32)StatsReturnAddr;
+
+ /* copy Nic stats to user's structure */
+ for (i = 0; i < (int) sizeof(RCLINKSTATS) / 4; i++)
+ pReturnAddr[i] = p32[i];


+
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================

+** Get82558LinkStatus()
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkStatus(U16 AdapterID, PU32 ReturnAddr, PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset;
+ volatile U32 timeout;
+ volatile PU32 pMsg;


+ volatile PU32 p32;
+ PPAB pPab;
+

+/*kprintf("Get82558LinkStatus() ReturnPhysAddr:0x%08.8ulx\n", ReturnAddr);*/


+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+

+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG

+ dprintf("Get82558LinkStatus(): Inbound Free Q empty!\n");
+#endif


+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);

+/*dprintf("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintf("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
+


+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;

+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;

+ pMsg[3] = 0x112; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS;


+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+

+ p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));

+ *p32 = 0xFFFFFFFF;
+

+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+

+ timeout = 100000;
+ while (1)
+ {
+ U32 i;


+
+ if (WaitCallback)
+ (*WaitCallback)();
+

+ for (i = 0; i < 1000; i++)
+ ;
+

+ if (*p32 != 0xFFFFFFFF)


+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG

+ kprintf("Timeout waiting for link status\n");
+#endif

+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+

+ *ReturnAddr = *p32; /* 1 = up 0 = down */


+
+ return RC_RTN_NO_ERROR;
+
+}

+
+/*
+** =========================================================================
+** RCGetMAC()
+**
+** get the MAC address the adapter is listening for in non-promiscous mode.
+** MAC address is in media format.
+** =========================================================================
+*/
+RC_RETURN
+RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback)
+{


+ unsigned i, timeout;
+ U32 off;

+ PU32 p;
+ U32 temp[2];


+ PPAB pPab;
+ PATU p_atu;
+

+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ p_atu = pPab->p_atu;
+

+ p_atu->EtherMacLow = 0; /* first zero return data */
+ p_atu->EtherMacHi = 0;
+

+ off = p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+

+ p = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+#ifdef RCDEBUG
+ printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n",
+ (uint)p_atu, (uint)off, (uint)p);
+#endif /* RCDEBUG */


+ /* setup private message */

+ p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ p[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ p[2] = 0; /* initiator context */
+ p[3] = 0x218; /* transaction context */
+ p[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_MAC_ADDR;
+


+
+ p_atu->InQueue = off; /* send it to the I2O device */

+#ifdef RCDEBUG
+ printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n",
+ (uint)p_atu, (uint)off, (uint)p);
+#endif /* RCDEBUG */


+
+ /* wait for the rcpci45 board to update the info */

+ timeout = 1000000;
+ while (0 == p_atu->EtherMacLow)

+ {
+ if (WaitCallback)
+ (*WaitCallback)();
+

+ for (i = 0; i < 1000; i++)
+ ;
+
+ if (!timeout--)
+ {

+ printk("rc_getmac: Timeout\n");


+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+

+ /* read the mac address */
+ temp[0] = p_atu->EtherMacLow;
+ temp[1] = p_atu->EtherMacHi;
+ memcpy((char *)mac, (char *)temp, 6);
+
+
+#ifdef RCDEBUG
+// printk("rc_getmac: 0x%X\n", ptr);
+#endif /* RCDEBUG */


+
+ return RC_RTN_NO_ERROR;
+}
+

+
+/*
+** =========================================================================
+** RCSetMAC()
+**
+** set MAC address the adapter is listening for in non-promiscous mode.
+** MAC address is in media format.
+** =========================================================================
+*/
+RC_RETURN
+RCSetMAC(U16 AdapterID, PU8 mac)
+{


+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+

+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */

+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_MAC_ADDR;
+ pMsg[5] = *(unsigned *)mac; /* first four bytes */
+ pMsg[6] = *(unsigned *)(mac + 4); /* last two bytes */


+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+

+ return RC_RTN_NO_ERROR ;
+}
+
+
+/*
+** =========================================================================

+** RCSetLinkSpeed()
+**
+** set ethernet link speed.
+** input: speedControl - determines action to take as follows
+** 0 = reset and auto-negotiate (NWay)


+** 1 = Full Duplex 100BaseT
+** 2 = Half duplex 100BaseT
+** 3 = Full Duplex 10BaseT
+** 4 = Half duplex 10BaseT

+** all other values are ignore (do nothing)
+** =========================================================================
+*/
+RC_RETURN
+RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode)


+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */

+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_LINK_SPEED;
+ pMsg[5] = LinkSpeedCode; /* link speed code */


+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+

+ return RC_RTN_NO_ERROR ;
+}
+/*
+** =========================================================================

+** RCSetPromiscuousMode()


+**
+** Defined values for Mode:
+** 0 - turn off promiscuous mode
+** 1 - turn on promiscuous mode
+**
+** =========================================================================
+*/

+RC_RETURN
+RCSetPromiscuousMode(U16 AdapterID, U16 Mode)

+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */

+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_PROMISCUOUS_MODE;
+ pMsg[5] = Mode; /* promiscuous mode setting */
+
+ pPab->p_atu->InQueue = off; /* send it to the device */


+
+ return RC_RTN_NO_ERROR ;
+}

+/*
+** =========================================================================
+** RCGetPromiscuousMode()


+**
+** get promiscuous mode setting
+**
+** Possible return values placed in pMode:
+** 0 = promisuous mode not set
+** 1 = promisuous mode is set
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)

+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+

+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ /* virtual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0xff;
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */

+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_PROMISCUOUS_MODE;

+/*
+** =========================================================================
+** RCSetBroadcastMode()


+**
+** Defined values for Mode:
+** 0 - turn off promiscuous mode
+** 1 - turn on promiscuous mode
+**
+** =========================================================================
+*/

+RC_RETURN
+RCSetBroadcastMode(U16 AdapterID, U16 Mode)

+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */

+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_BROADCAST_MODE;
+ pMsg[5] = Mode; /* promiscuous mode setting */
+
+ pPab->p_atu->InQueue = off; /* send it to the device */


+
+ return RC_RTN_NO_ERROR ;
+}

+/*
+** =========================================================================
+** RCGetBroadcastMode()


+**
+** get promiscuous mode setting
+**
+** Possible return values placed in pMode:
+** 0 = promisuous mode not set
+** 1 = promisuous mode is set
+**
+** =========================================================================
+*/
+RC_RETURN

+RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)

+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+

+ msgOffset = pPab->p_atu->InQueue;
+

SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 06'
echo 'File patch-2.2.0-pre8 is continued in part 07'
echo 07 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part09

#!/bin/sh
# this is part 09 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 09; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

-
- /* post to Inbound Post Q */
- pPab->p_atu->InQueue = msgOffset;
-
- return RC_RTN_NO_ERROR;
-}
-
-
-/*
-** =========================================================================
-** FillI12OMsgFromTCB()
-**
-** inputs pMsgU32 - virual pointer (mapped to physical) of message frame
-** pXmitCntrlBlock - pointer to caller buffer control block.
-**
-** fills in LAN SGL after Transaction Control Word or Bucket Count.
-** =========================================================================
-*/
-static int
-FillAdapterMsgSGLFromTCB(PU32 pMsgFrame, PRCTCB pTransCtrlBlock)
-{
- unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags;
- PU32 pTCB, pMsg;
-
- /* SGL element flags */
-#define EOB 0x40000000
-#define LE 0x80000000
-#define SIMPLE_SGL 0x10000000
-#define BC_PRESENT 0x01000000
-
- pTCB = (PU32)pTransCtrlBlock;
- pMsg = pMsgFrame;
- nmbrDwords = 0;
-
-#ifdef DEBUG
- kprintf("FillAdapterMsgSGLFromTCBX\n");
-kprintf("TCB 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
- pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]);
-kprintf("pTCB 0x%08.8ulx, pMsg 0x%08.8ulx\n", pTCB, pMsg);
-#endif /* DEBUG */
-
- nmbrBuffers = *pTCB++;
-
- if (!nmbrBuffers)
- {


- return -1;
- }
-

- do
- {
- context = *pTCB++; /* buffer tag (context) */
- nmbrSeg = *pTCB++; /* number of segments */
-
- if (!nmbrSeg)
- {


- return -1;
- }
-

- flags = SIMPLE_SGL | BC_PRESENT;
-
- if (1 == nmbrSeg)
- {
- flags |= EOB;
-
- if (1 == nmbrBuffers)
- flags |= LE;
- }
-
- /* 1st SGL buffer element has context */
- pMsg[0] = pTCB[0] | flags ; /* send over count (segment size) */
- pMsg[1] = context;
- pMsg[2] = pTCB[1]; /* send buffer segment physical address */
- nmbrDwords += 3;
- pMsg += 3;
- pTCB += 2;
-
-
- if (--nmbrSeg)
- {
- do
- {
- flags = SIMPLE_SGL;
-
- if (1 == nmbrSeg)
- {
- flags |= EOB;
-
- if (1 == nmbrBuffers)
- flags |= LE;
- }
-
- pMsg[0] = pTCB[0] | flags; /* send over count */
- pMsg[1] = pTCB[1]; /* send buffer segment physical address */
- nmbrDwords += 2;
- pTCB += 2;
- pMsg += 2;
-
- } while (--nmbrSeg);
- }
-
- } while (--nmbrBuffers);
-
- return nmbrDwords;
-}
-
-
-/*
-** =========================================================================
-** ProcessOutboundAdapterMsg()
-**
-** process reply message
-** * change to msg structure *
-** =========================================================================
-*/
-static void
-ProcessOutboundAdapterMsg(PPAB pPab, U32 phyAddrMsg)
-{
- PU8 p8Msg;
- PU32 p32;
- // U16 count;
-
-
- p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
- p32 = (PU32)p8Msg;
-
-#ifdef DEBUG
- kprintf("VXD: ProcessOutboundAdapterMsg - pPab 0x%08.8ulx, phyAdr 0x%08.8ulx, linAdr 0x%08.8ulx\n", pPab, phyAddrMsg, p8Msg);
- kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
- kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
-#endif /* DEBUG */
-
- if (p32[4] >> 24 != RC_REPLY_STATUS_SUCCESS)
- {
-#ifdef DEBUG
- kprintf("Message reply status not success\n");
-#endif /* DEBUG */
- return;
- }
-
- switch (p8Msg[7] ) /* function code byte */
- {
- case RC_CMD_SYS_TAB_SET:
- msgFlag = 1;
-#ifdef DEBUG
- kprintf("Received RC_CMD_SYS_TAB_SET reply\n");
-#endif /* DEBUG */
- break;
-
- case RC_CMD_HRT_GET:
- msgFlag = 1;
-#ifdef DEBUG
- kprintf("Received RC_CMD_HRT_GET reply\n");
-#endif /* DEBUG */
- break;
-
- case RC_CMD_LCT_NOTIFY:
- msgFlag = 1;
-#ifdef DEBUG
- kprintf("Received RC_CMD_LCT_NOTIFY reply\n");
-#endif /* DEBUG */
- break;
-
- case RC_CMD_SYS_ENABLE:
- msgFlag = 1;
-#ifdef DEBUG
- kprintf("Received RC_CMD_SYS_ENABLE reply\n");
-#endif /* DEBUG */
- break;
-
- default:
-#ifdef DEBUG
- kprintf("Received UNKNOWN reply\n");
-#endif /* DEBUG */
- break;
- }
-}
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/rcmtl.h linux/drivers/net/rcmtl.h
--- v2.2.0-pre7/linux/drivers/net/rcmtl.h Fri Jan 8 22:36:07 1999
+++ linux/drivers/net/rcmtl.h Wed Dec 31 16:00:00 1969
@@ -1,580 +0,0 @@


-/*
-** *************************************************************************
-**
-**

-** R C M T L . H $Revision: 3 $
-**
-**
-** RedCreek Message Transport Layer header file.


-**
-** ---------------------------------------------------------------------
-** --- Copyright (c) 1997-1998, RedCreek Communications Inc. ---
-** --- All rights reserved. ---
-** ---------------------------------------------------------------------
-**
-** File Description:
-**

-** Header file for host message transport layer API and data types.
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-** *************************************************************************
-*/
-
-#ifndef RCMTL_H
-#define RCMTL_H
-
-/* Linux specific includes */
-#define kprintf printk
-#ifdef RC_LINUX_MODULE /* linux modules need non-library version of string functions */
-#include <linux/string.h>
-#else
-#include <string.h>
-#endif
-
-/* PCI/45 Configuration space values */
-#define RC_PCI45_VENDOR_ID 0x4916
-#define RC_PCI45_DEVICE_ID 0x1960
-
-
- /* RedCreek API function return values */
-#define RC_RTN_NO_ERROR 0
-#define RC_RTN_NOT_INIT 1
-#define RC_RTN_FREE_Q_EMPTY 2
-#define RC_RTN_TCB_ERROR 3
-#define RC_RTN_TRANSACTION_ERROR 4
-#define RC_RTN_ADAPTER_ALREADY_INIT 5
-#define RC_RTN_MALLOC_ERROR 6
-#define RC_RTN_ADPTR_NOT_REGISTERED 7
-#define RC_RTN_MSG_REPLY_TIMEOUT 8
-#define RC_RTN_NO_STATUS 9
-#define RC_RTN_NO_FIRM_VER 10
-#define RC_RTN_NO_LINK_SPEED 11
-
-/* Driver capability flags */
-#define WARM_REBOOT_CAPABLE 0x01
-
- /* scalar data types */
-typedef unsigned char U8;
-typedef unsigned char* PU8;
-typedef unsigned short U16;
-typedef unsigned short* PU16;
-typedef unsigned long U32;
-typedef unsigned long* PU32;
-typedef unsigned long BF;
-typedef int RC_RETURN;
-
-
- /*
- ** type PFNWAITCALLBACK
- **
- ** pointer to void function - type used for WaitCallback in some functions
- */
-typedef void (*PFNWAITCALLBACK)(void); /* void argument avoids compiler complaint */
-
- /*
- ** type PFNTXCALLBACK
- **
- ** Pointer to user's transmit callback function. This user function is
- ** called from RCProcMsgQ() when packet have been transmitted from buffers
- ** given in the RCSendPacket() function. BufferContext is a pointer to
- ** an array of 32 bit context values. These are the values the user assigned
- ** and passed in the TCB to the RCSendPacket() function. PcktCount
- ** indicates the number of buffer context values in the BufferContext[] array.
- ** The User's TransmitCallbackFunction should recover (put back in free queue)
- ** the packet buffers associated with the buffer context values.
- */
-typedef void (*PFNTXCALLBACK)(U32 Status,
- U16 PcktCount,
- PU32 BufferContext,
- U16 AdaterID);
-
- /*
- ** type PFNRXCALLBACK
- **
- ** Pointer to user's receive callback function. This user function
- ** is called from RCProcMsgQ() when packets have been received into
- ** previously posted packet buffers throught the RCPostRecvBuffers() function.
- ** The received callback function should process the Packet Descriptor Block
- ** pointed to by PacketDescBlock. See Packet Decription Block below.
- */
-typedef void (*PFNRXCALLBACK)(U32 Status,
- U8 PktCount,
- U32 BucketsRemain,
- PU32 PacketDescBlock,
- U16 AdapterID);
-
- /*
- ** type PFNCALLBACK
- **
- ** Pointer to user's generic callback function. This user function
- ** can be passed to LANReset or LANShutdown and is called when the
- ** the reset or shutdown is complete.
- ** Param1 and Param2 are invalid for LANReset and LANShutdown.
- */
-typedef void (*PFNCALLBACK)(U32 Status,
- U32 Param1,
- U32 Param2,
- U16 AdapterID);
-
-/*
-** Status - Transmit and Receive callback status word
-**
-** A 32 bit Status is returned to the TX and RX callback functions. This value
-** contains both the reply status and the detailed status as follows:
-**
-** 32 24 16 0
-** +------+------+------------+
-** | Reply| | Detailed |
-** |Status| 0 | Status |
-** +------+------+------------+
-**
-** Reply Status and Detailed Status of zero indicates No Errors.
-*/
- /* reply message status defines */
-#define RC_REPLY_STATUS_SUCCESS 0x00
-#define RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
-#define RC_REPLY_STATUS_TRANSACTION_ERROR 0x0A
-
-
-/* DetailedStatusCode defines */
-#define RC_DSC_SUCCESS 0x0000
-#define RC_DSC_DEVICE_FAILURE 0x0001
-#define RC_DSC_DESTINATION_NOT_FOUND 0x0002
-#define RC_DSC_TRANSMIT_ERROR 0x0003
-#define RC_DSC_TRANSMIT_ABORTED 0x0004
-#define RC_DSC_RECEIVE_ERROR 0x0005
-#define RC_DSC_RECEIVE_ABORTED 0x0006
-#define RC_DSC_DMA_ERROR 0x0007
-#define RC_DSC_BAD_PACKET_DETECTED 0x0008
-#define RC_DSC_OUT_OF_MEMORY 0x0009
-#define RC_DSC_BUCKET_OVERRUN 0x000A
-#define RC_DSC_IOP_INTERNAL_ERROR 0x000B
-#define RC_DSC_CANCELED 0x000C
-#define RC_DSC_INVALID_TRANSACTION_CONTEXT 0x000D
-#define RC_DSC_DESTINATION_ADDRESS_DETECTED 0x000E
-#define RC_DSC_DESTINATION_ADDRESS_OMITTED 0x000F
-#define RC_DSC_PARTIAL_PACKET_RETURNED 0x0010
-
-
-/*
-** Packet Description Block (Received packets)
-**
-** A pointer to this block structure is returned to the ReceiveCallback
-** function. It contains the list of packet buffers which have either been
-** filled with a packet or returned to host due to a LANReset function.
-** Currently there will only be one packet per receive bucket (buffer) posted.
-**
-** 32 24 0
-** +-----------------------+ -\
-** | Buffer 1 Context | \
-** +-----------------------+ \
-** | 0xC0000000 | / First Bucket Descriptor
-** +-----+-----------------+ /
-** | 0 | packet 1 length | /
-** +-----------------------+ -\
-** | Buffer 2 Context | \
-** +-----------------------+ \
-** | 0xC0000000 | / Second Bucket Descriptor
-** +-----+-----------------+ /
-** | 0 | packet 2 length | /
-** +-----+-----------------+ -
-** | ... | ----- more bucket descriptors
-** +-----------------------+ -\
-** | Buffer n Context | \
-** +-----------------------+ \
-** | 0xC0000000 | / Last Bucket Descriptor
-** +-----+-----------------+ /
-** | 0 | packet n length | /
-** +-----+-----------------+ -
-**
-** Buffer Context values are those given to adapter in the TCB on calls to
-** RCPostRecvBuffers().
-**
-*/
-
-
-
-/*
-** Transaction Control Block (TCB) structure
-**
-** A structure like this is filled in by the user and passed by reference to
-** RCSendPacket() and RCPostRecvBuffers() functions. Minimum size is five
-** 32-bit words for one buffer with one segment descriptor.
-** MAX_NMBR_POST_BUFFERS_PER_MSG defines the maximum single segment buffers
-** that can be described in a given TCB.
-**
-** 32 0
-** +-----------------------+
-** | Buffer Count | Number of buffers in the TCB
-** +-----------------------+
-** | Buffer 1 Context | first buffer reference
-** +-----------------------+
-** | Buffer 1 Seg Count | number of segments in buffer
-** +-----------------------+
-** | Buffer 1 Seg Desc 1 | first segment descriptor (size, physical address)
-** +-----------------------+
-** | ... | more segment descriptors (size, physical address)
-** +-----------------------+
-** | Buffer 1 Seg Desc n | last segment descriptor (size, physical address)
-** +-----------------------+
-** | Buffer 2 Context | second buffer reference
-** +-----------------------+
-** | Buffer 2 Seg Count | number of segments in buffer
-** +-----------------------+
-** | Buffer 2 Seg Desc 1 | segment descriptor (size, physical address)
-** +-----------------------+
-** | ... | more segment descriptors (size, physical address)
-** +-----------------------+
-** | Buffer 2 Seg Desc n |
-** +-----------------------+
-** | ... | more buffer descriptor blocks ...
-** +-----------------------+
-** | Buffer n Context |
-** +-----------------------+
-** | Buffer n Seg Count |
-** +-----------------------+
-** | Buffer n Seg Desc 1 |
-** +-----------------------+
-** | ... |
-** +-----------------------+
-** | Buffer n Seg Desc n |
-** +-----------------------+
-**
-**
-** A TCB for one contigous packet buffer would look like the following:
-**
-** 32 0
-** +-----------------------+
-** | 1 | one buffer in the TCB
-** +-----------------------+
-** | <user's Context> | user's buffer reference
-** +-----------------------+
-** | 1 | one segment buffer
-** +-----------------------+ _
-** | <buffer size> | size \
-** +-----------------------+ \ segment descriptor
-** | <physical address> | physical address of buffer /
-** +-----------------------+ _/
-**
-*/
-
- /* Buffer Segment Descriptor */
-typedef struct
-{
- U32 size;
- U32 phyAddress;
-}
- BSD, *PBSD;
-
-typedef PU32 PRCTCB;
-/*
-** -------------------------------------------------------------------------
-** Exported functions comprising the API to the message transport layer
-** -------------------------------------------------------------------------
-*/
-
-
- /*
- ** InitRCApiMsgLayer()
- **
- ** Called once prior to using the API message transport layer. User
- ** provides both the physical and virual address of a locked page buffer
- ** that is used as a private buffer for the RedCreek API message
- ** transport layer. This buffer must be a contigous memory block of a
- ** minimum of 16K bytes and long word aligned. The user also must provide
- ** the base address of the RedCreek PCI adapter assigned by BIOS or operating
- ** system. The user provided value AdapterID is a zero based index of the
- ** Ravlin 45/PCI adapter. This interface number is used in all subsequent API
- ** calls to identify which adpapter for which the function is intended.
- ** Up to sixteen interfaces are supported with this API.
- **
- ** Inputs: AdapterID - interface number from 0 to 15
- ** pciBaseAddr - virual base address of PCI (set by BIOS)
- ** p_msgbuf - virual address to private message block (min. 16K)
- ** p_phymsgbuf - physical address of private message block
- ** TransmitCallbackFunction - address of user's TX callback function
- ** ReceiveCallbackFunction - address of user's RX callback function
- **
- */
-RC_RETURN InitRCApiMsgLayer(U16 AdapterID, U32 pciBaseAddr,
- PU8 p_msgbuf, PU8 p_phymsgbuf,
- PFNTXCALLBACK TransmitCallbackFunction,
- PFNRXCALLBACK ReceiveCallbackFunction,
- PFNCALLBACK RebootCallbackFunction);
-
- /*
- ** RCSetRavlinIPandMask()
- **
- ** Set the Ravlin 45/PCI cards IP address and network mask.
- **
- ** IP address and mask must be in network byte order.
- ** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
- ** 0x04030201 and 0x00FFFFFF on a little endian machine.
- **
- */
-RC_RETURN RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask);
-
-
-/*
-** =========================================================================
-** RCGetRavlinIPandMask()
-**
-** get the IP address and MASK from the card
-**
-** =========================================================================
-*/
-RC_RETURN
-RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask,
- PFNWAITCALLBACK WaitCallback);
-
- /*
- ** RCProcMsgQ()
- **
- ** Called from user's polling loop or Interrupt Service Routine for a PCI
- ** interrupt from the RedCreek PCI adapter. User responsible for determining
- ** and hooking the PCI interrupt. This function will call the registered
- ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
- ** if a TX or RX transaction has completed.
- */
-void RCProcMsgQ(U16 AdapterID);
-
-
- /*
- ** Disable and Enable Adapter interrupts. Adapter interrupts are enabled at
- ** Init time but can be disabled and re-enabled through these two function calls.
- ** Packets will still be put into any posted received buffers and packets will
- ** be sent through RCSendPacket() functions. Disabling Adapter interrupts
- ** will prevent hardware interrupt to host even though the outbound msg
- ** queue is not emtpy.
- */
-RC_RETURN RCEnableAdapterInterrupts(U16 adapterID);
-RC_RETURN RCDisableAdapterInterrupts(U16 AdapterID);
-
-
- /*
- ** RCPostRecvBuffers()
- **
- ** Post user's page locked buffers for use by the PCI adapter to
- ** return ethernet packets received from the LAN. Transaction Control Block,
- ** provided by user, contains buffer descriptor(s) which includes a buffer
- ** context number along with buffer size and physical address. See TCB above.
- ** The buffer context and actual packet length are returned to the
- ** ReceiveCallbackFunction when packets have been received. Buffers posted
- ** to the RedCreek adapter are considered owned by the adapter until the
- ** context is return to user through the ReceiveCallbackFunction.
- */
-RC_RETURN RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransactionCtrlBlock);
-#define MAX_NMBR_POST_BUFFERS_PER_MSG 32
-
- /*
- ** RCSendPacket()
- **
- ** Send user's ethernet packet from a locked page buffer.
- ** Packet must have full MAC header, however without a CRC.
- ** Initiator context is a user provided value that is returned
- ** to the TransmitCallbackFunction when packet buffer is free.
- ** Transmit buffer are considered owned by the adapter until context's
- ** returned to user through the TransmitCallbackFunction.
- */
-RC_RETURN RCSendPacket(U16 AdapterID,
- U32 context,
- PRCTCB pTransactionCtrlBlock);
-
-
- /* Ethernet Link Statistics structure */
-typedef struct tag_RC_link_stats
-{
- U32 TX_good; /* good transmit frames */
- U32 TX_maxcol; /* frames not TX due to MAX collisions */
- U32 TX_latecol; /* frames not TX due to late collisions */
- U32 TX_urun; /* frames not TX due to DMA underrun */
- U32 TX_crs; /* frames TX with lost carrier sense */
- U32 TX_def; /* frames deferred due to activity on link */
- U32 TX_singlecol; /* frames TX with one and only on collision */
- U32 TX_multcol; /* frames TX with more than one collision */
- U32 TX_totcol; /* total collisions detected during TX */
- U32 Rcv_good; /* good frames received */
- U32 Rcv_CRCerr; /* frames RX and discarded with CRC errors */
- U32 Rcv_alignerr; /* frames RX with alignment and CRC errors */
- U32 Rcv_reserr; /* good frames discarded due to no RX buffer */
- U32 Rcv_orun; /* RX frames lost due to FIFO overrun */
- U32 Rcv_cdt; /* RX frames with collision during RX */
- U32 Rcv_runt; /* RX frames shorter than 64 bytes */
-}
- RCLINKSTATS, *P_RCLINKSTATS;
-
- /*
- ** RCGetLinkStatistics()
- **
- ** Returns link statistics in user's structure at address StatsReturnAddr
- ** If given, not NULL, the function WaitCallback is called during the wait
- ** loop while waiting for the adapter to respond.
- */
-RC_RETURN RCGetLinkStatistics(U16 AdapterID,
- P_RCLINKSTATS StatsReturnAddr,
- PFNWAITCALLBACK WaitCallback);
-
- /*
- ** RCGetLinkStatus()
- **
- ** Return link status, up or down, to user's location addressed by ReturnAddr.
- ** If given, not NULL, the function WaitCallback is called during the wait
- ** loop while waiting for the adapter to respond.
- */
-RC_RETURN RCGetLinkStatus(U16 AdapterID,
- PU32 pReturnStatus,
- PFNWAITCALLBACK WaitCallback);
-
- /* Link Status defines - value returned in pReturnStatus */
-#define LAN_LINK_STATUS_DOWN 0
-#define LAN_LINK_STATUS_UP 1
-
- /*
- ** RCGetMAC()
- **
- ** Get the current MAC address assigned to user. RedCreek Ravlin 45/PCI
- ** has two MAC addresses. One which is private to the PCI Card, and
- ** another MAC which is given to the user as its link layer MAC address. The
- ** adapter runs in promiscous mode because of the dual address requirement.
- ** The MAC address is returned to the unsigned char array pointer to by mac.
- */
-RC_RETURN RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback);
-
- /*
- ** RCSetMAC()
- **
- ** Set a new user port MAC address. This address will be returned on
- ** subsequent RCGetMAC() calls.
- */
-RC_RETURN RCSetMAC(U16 AdapterID, PU8 mac);
-
- /*
- ** RCSetLinkSpeed()
- **
- ** set adapter's link speed based on given input code.
- */
-RC_RETURN RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode);
- /* Set link speed codes */
-#define LNK_SPD_AUTO_NEG_NWAY 0
-#define LNK_SPD_100MB_FULL 1
-#define LNK_SPD_100MB_HALF 2
-#define LNK_SPD_10MB_FULL 3
-#define LNK_SPD_10MB_HALF 4
-
-
-
-
- /*
- ** RCGetLinkSpeed()
- **
- ** Return link speed code.
- */
- /* Return link speed codes */
-#define LNK_SPD_UNKNOWN 0
-#define LNK_SPD_100MB_FULL 1
-#define LNK_SPD_100MB_HALF 2
-#define LNK_SPD_10MB_FULL 3
-#define LNK_SPD_10MB_HALF 4
-
-RC_RETURN
-RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
-
-/*
-** =========================================================================
-** RCReportDriverCapability(U16 AdapterID, U32 capability)
-**
-** Currently defined bits:
-** WARM_REBOOT_CAPABLE 0x01
-**
-** =========================================================================
-*/
-RC_RETURN
-RCReportDriverCapability(U16 AdapterID, U32 capability);
-
-/*
-** RCGetFirmwareVer()
-**
-** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
-**
-** WARNING: user's space pointed to by pFirmString should be at least 60 bytes.
-*/
-RC_RETURN
-RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback);
-
-/*
-** ----------------------------------------------
-** LAN adapter Reset and Shutdown functions
-** ----------------------------------------------
-*/
- /* resource flag bit assignments for RCResetLANCard() & RCShutdownLANCard() */
-#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS 0x0001
-#define RC_RESOURCE_RETURN_PEND_TX_BUFFERS 0x0002
-
- /*
- ** RCResetLANCard()
- **
- ** Reset LAN card operation. Causes a software reset of the ethernet
- ** controller and restarts the command and receive units. Depending on
- ** the ResourceFlags given, the buffers are either returned to the
- ** host with reply status of RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and
- ** detailed status of RC_DSC_CANCELED (new receive buffers must be
- ** posted after issuing this) OR the buffers are kept and reused by
- ** the ethernet controller. If CallbackFunction is not NULL, the function
- ** will be called when the reset is complete. If the CallbackFunction is
- ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset
- ** to complete (please disable adapter interrupts during this method).
- ** Any outstanding transmit or receive buffers that are complete will be
- ** returned via the normal reply messages before the requested resource
- ** buffers are returned.
- ** A call to RCPostRecvBuffers() is needed to return the ethernet to full
- ** operation if the receive buffers were returned during LANReset.
- ** Note: The IOP status is not affected by a LAN reset.
- */
-RC_RETURN RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
-
-
- /*
- ** RCShutdownLANCard()
- **
- ** Shutdown LAN card operation and put into an idle (suspended) state.
- ** The LAN card is restarted with RCResetLANCard() function.
- ** Depending on the ResourceFlags given, the buffers are either returned
- ** to the host with reply status of RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER
- ** and detailed status of RC_DSC_CANCELED (new receive buffers must be
- ** posted after issuing this) OR the buffers are kept and reused by
- ** the ethernet controller. If CallbackFunction is not NULL, the function
- ** will be called when the reset is complete. If the CallbackFunction is
- ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset
- ** to complete (please disable adapter interrupts during this method).
- ** Any outstanding transmit or receive buffers that are complete will be
- ** returned via the normal reply messages before the requested resource
- ** buffers are returned.
- ** Note: The IOP status is not affected by a LAN shutdown.
- */
-RC_RETURN
-RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
-
- /*
- ** RCResetAdapter();
- ** Initializes ADAPTERState to ADAPTER_STATE_RESET.
- ** Stops access to outbound message Q.
- ** Discards any outstanding transmit or posted receive buffers.
- ** Clears outbound message Q.
- */
-RC_RETURN
-RCResetAdapter(U16 AdapterID);
-
-#endif /* RCMTL_H */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- v2.2.0-pre7/linux/drivers/net/rcpci45.c Tue Dec 22 14:16:56 1998
+++ linux/drivers/net/rcpci45.c Thu Jan 14 22:58:47 1999
@@ -4,7 +4,7 @@
X **


X **
X ** ---------------------------------------------------------------------
-** --- Copyright (c) 1998, RedCreek Communications Inc. ---

+** --- Copyright (c) 1998, 1999, RedCreek Communications Inc. ---


X ** --- All rights reserved. ---
X ** ---------------------------------------------------------------------
X **

@@ -12,14 +12,13 @@
X **
X ** Known Problems
X **
-** Billions and Billions...
-**
-** ... apparently added by Brian. Pete knows of no bugs.
+** None known at this time.
X **
X ** TODO:
X ** -Get rid of the wait loops in the API and replace them
X ** with system independent delays ...something like
-** "delayms(2)".
+** "delayms(2)". However, under normal circumstances, the
+** delays are very short so they're not a problem.
X **
X ** This program is free software; you can redistribute it and/or modify
X ** it under the terms of the GNU General Public License as published by
@@ -35,14 +34,18 @@
X ** along with this program; if not, write to the Free Software
X ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X **
+**
+** Pete Popov, January 11,99: Fixed a couple of 2.1.x problems
+** (virt_to_bus() not called), tested it under 2.2pre5, and added a
+** #define to enable the use of the same file for both, the 2.0.x kernels
+** as well as the 2.1.x.
X **
-** Ported to 2.1.x by Alan Cox 1998/12/9. If this doesnt work try 2.0.x
-** and let me know.
+** Ported to 2.1.x by Alan Cox 1998/12/9.
X **
X ***************************************************************************/
X
X static char *version =
-"RedCreek Communications PCI linux driver version 1.32 Beta\n";
+"RedCreek Communications PCI linux driver version 2.00\n";
X
X
X #include <linux/module.h>
@@ -63,27 +66,34 @@
X #include <asm/bitops.h>
X #include <asm/io.h>


X
+#if LINUX_VERSION_CODE >= 0x020100

+#define LINUX_2_1
+#endif
+
+#ifdef LINUX_2_1


X #include <asm/uaccess.h>
+#endif
X

X #include <linux/if_ether.h>
X #include <linux/netdevice.h>
X #include <linux/etherdevice.h>
X #include <linux/skbuff.h>
X
+
X #define RC_LINUX_MODULE
-#include "rcmtl.h"
+#include "rclanmtl.h"
X #include "rcif.h"
X
X #define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
-
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
X
X #define NEW_MULTICAST
X #include <linux/delay.h>
X
+#ifndef LINUX_2_1


+#define ioremap vremap
+#define iounmap vfree
+#endif
+

X /* PCI/45 Configuration space values */
X #define RC_PCI45_VENDOR_ID 0x4916
X #define RC_PCI45_DEVICE_ID 0x1960
@@ -111,25 +121,25 @@
X typedef struct
X {
X
- /*
- * pointer to the device structure which is part
- * of the interface to the Linux kernel.
- */
- struct device *dev;
+ /*
+ * pointer to the device structure which is part
+ * of the interface to the Linux kernel.
+ */
+ struct device *dev;
X
- char devname[8]; /* "ethN" string */
- U8 id; /* the AdapterID */
- U32 pci_addr; /* the pci address of the adapter */
- U32 bus;
- U32 function;
- struct timer_list timer; /* timer */
- struct enet_statistics stats; /* the statistics structure */
- struct device *next; /* points to the next RC adapter */
- unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/
- unsigned char shutdown;
- unsigned char reboot;
- unsigned char nexus;
- PU8 PLanApiPA; /* Pointer to Lan Api Private Area */
+ char devname[8]; /* "ethN" string */
+ U8 id; /* the AdapterID */
+ U32 pci_addr; /* the pci address of the adapter */
+ U32 bus;
+ U32 function;
+ struct timer_list timer; /* timer */
+ struct enet_statistics stats; /* the statistics structure */
+ struct device *next; /* points to the next RC adapter */
+ unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/
+ unsigned char shutdown;
+ unsigned char reboot;
+ unsigned char nexus;
+ PU8 PLanApiPA; /* Pointer to Lan Api Private Area */
X
X }
X DPA, *PDPA;
@@ -138,10 +148,10 @@
X
X static PDPA PCIAdapters[MAX_ADAPTERS] =
X {
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL


+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL

X };
X
X
@@ -173,258 +183,258 @@
X int rcpci_probe(struct netdevice *dev)
X #endif
X {
- int cards_found;
+ int cards_found;
X
- printk(version);
+ printk(version);
X
- root_RCdev = NULL;
- cards_found = RCscan();
-#ifdef MODULE
- return cards_found ? 0 : -ENODEV;
+ root_RCdev = NULL;
+ cards_found = RCscan();
+#ifdef MODULE
+ return cards_found ? 0 : -ENODEV;
X #else
- return -1;
-#endif
+ return -1;
+#endif
X }
X
-static int RCscan(void)
+static int RCscan()
X {
- int cards_found = 0;
- struct device *dev = 0;
+ int cards_found = 0;
+ struct device *dev = 0;
+
+ if (pcibios_present())
+ {
+ static int pci_index = 0;
+ unsigned char pci_bus, pci_device_fn;
+ int scan_status;
+ int board_index = 0;
X
- if (pcibios_present())
- {
- static int pci_index = 0;
- unsigned char pci_bus, pci_device_fn;
- int scan_status;
- int board_index = 0;
-
- for (;pci_index < 0xff; pci_index++)
- {
- unsigned char pci_irq_line;
- unsigned short pci_command, vendor, device, class;
- unsigned int pci_ioaddr;
-
-
- scan_status =
- (pcibios_find_device (RC_PCI45_VENDOR_ID,
- RC_PCI45_DEVICE_ID,
- pci_index,
- &pci_bus,
- &pci_device_fn));
-#ifdef RCDEBUG
- printk("rc scan_status = 0x%X\n", scan_status);
-#endif
- if (scan_status != PCIBIOS_SUCCESSFUL)
- break;
- pcibios_read_config_word(pci_bus,
- pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus,
- pci_device_fn,
- PCI_DEVICE_ID, &device);
- pcibios_read_config_byte(pci_bus,
- pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- pcibios_read_config_dword(pci_bus,
- pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- pcibios_read_config_word(pci_bus,
- pci_device_fn,
- PCI_CLASS_DEVICE, &class);
-
- pci_ioaddr &= ~0xf;
-
-#ifdef RCDEBUG
- printk("rc: Found RedCreek PCI adapter\n");
- printk("rc: pci class = 0x%x 0x%x \n", class, class>>8);
- printk("rc: pci_bus = %d, pci_device_fn = %d\n", pci_bus, pci_device_fn);
- printk("rc: pci_irq_line = 0x%x \n", pci_irq_line);
- printk("rc: pci_ioaddr = 0x%x\n", pci_ioaddr);
-#endif
-
-#if 0
- if (check_region(pci_ioaddr, 32768))
- {
- printk("rc: check_region failed\n");
- continue;
- }
- else
- {
- printk("rc: check_region passed\n");
- }
+ for (;pci_index < 0xff; pci_index++)
+ {
+ unsigned char pci_irq_line;
+ unsigned short pci_command, vendor, device, class;
+ unsigned int pci_ioaddr;
+
+
+ scan_status =
+ (pcibios_find_device (RC_PCI45_VENDOR_ID,
+ RC_PCI45_DEVICE_ID,
+ pci_index,
+ &pci_bus,
+ &pci_device_fn));
+#ifdef RCDEBUG
+ printk("rc scan_status = 0x%X\n", scan_status);
+#endif
+ if (scan_status != PCIBIOS_SUCCESSFUL)
+ break;
+ pcibios_read_config_word(pci_bus,
+ pci_device_fn,
+ PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(pci_bus,
+ pci_device_fn,
+ PCI_DEVICE_ID, &device);
+ pcibios_read_config_byte(pci_bus,
+ pci_device_fn,
+ PCI_INTERRUPT_LINE, &pci_irq_line);
+ pcibios_read_config_dword(pci_bus,
+ pci_device_fn,
+ PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ pcibios_read_config_word(pci_bus,
+ pci_device_fn,
+ PCI_CLASS_DEVICE, &class);
+
+ pci_ioaddr &= ~0xf;
+
+#ifdef RCDEBUG
+ printk("rc: Found RedCreek PCI adapter\n");
+ printk("rc: pci class = 0x%x 0x%x \n", class, class>>8);
+ printk("rc: pci_bus = %d, pci_device_fn = %d\n", pci_bus, pci_device_fn);
+ printk("rc: pci_irq_line = 0x%x \n", pci_irq_line);
+ printk("rc: pci_ioaddr = 0x%x\n", pci_ioaddr);
X #endif
-
- /*
- * Get and check the bus-master and latency values.
- * Some PCI BIOSes fail to set the master-enable bit.
- */
X
- pcibios_read_config_word(pci_bus,
- pci_device_fn,
- PCI_COMMAND,
- &pci_command);
- if ( ! (pci_command & PCI_COMMAND_MASTER)) {
- printk("rc: PCI Master Bit has not been set!\n");
+#if 1
+ if (check_region(pci_ioaddr, 2*32768))
+ {
+ printk("rc: check_region failed\n");
+ continue;
+ }
+ else
+ {
+ printk("rc: check_region passed\n");
+ }
+#endif
+
+ /*
+ * Get and check the bus-master and latency values.
+ * Some PCI BIOSes fail to set the master-enable bit.
+ */
+
+ pcibios_read_config_word(pci_bus,
+ pci_device_fn,
+ PCI_COMMAND,
+ &pci_command);
+ if ( ! (pci_command & PCI_COMMAND_MASTER)) {
+ printk("rc: PCI Master Bit has not been set!\n");
X
- pci_command |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(pci_bus,
- pci_device_fn,
- PCI_COMMAND,
- pci_command);
- }
- if ( ! (pci_command & PCI_COMMAND_MEMORY)) {
+ pci_command |= PCI_COMMAND_MASTER;
+ pcibios_write_config_word(pci_bus,
+ pci_device_fn,
+ PCI_COMMAND,
+ pci_command);
+ }
+ if ( ! (pci_command & PCI_COMMAND_MEMORY)) {
X /*
X * If the BIOS did not set the memory enable bit, what else
X * did it not initialize? Skip this adapter.
X */
- printk("rc: Adapter %d, PCI Memory Bit has not been set!\n",
- cards_found);
- printk("rc: Bios problem? \n");
- continue;
- }
+ printk("rc: Adapter %d, PCI Memory Bit has not been set!\n",
+ cards_found);
+ printk("rc: Bios problem? \n");
+ continue;
+ }
X
- dev = RCfound_device(dev, pci_ioaddr, pci_irq_line,
- pci_bus, pci_device_fn,
- board_index++, cards_found);
-
- if (dev) {
- dev = 0;
- cards_found++;
- }
- }
- }
- printk("rc: found %d cards \n", cards_found);
- return cards_found;
+ dev = RCfound_device(dev, pci_ioaddr, pci_irq_line,
+ pci_bus, pci_device_fn,
+ board_index++, cards_found);
+
+ if (dev) {
+ dev = 0;
+ cards_found++;
+ }
+ }
+ }
+ printk("rc: found %d cards \n", cards_found);
+ return cards_found;
X }
X
X static struct device *
X RCfound_device(struct device *dev, int memaddr, int irq,
X int bus, int function, int product_index, int card_idx)
X {
- int dev_size = 32768;
- unsigned long *vaddr=0;
- PDPA pDpa;
- int init_status;
-
- /*
- * Allocate and fill new device structure.
- * We need enough for struct device plus DPA plus the LAN API private
- * area, which requires a minimum of 16KB. The top of the allocated
- * area will be assigned to struct device; the next chunk will be
- * assigned to DPA; and finally, the rest will be assigned to the
- * the LAN API layer.
- */
- dev = (struct device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
- memset(dev, 0, dev_size);
+ int dev_size = 32768;
+ unsigned long *vaddr=0;
+ PDPA pDpa;
+ int init_status;
+
+ /*
+ * Allocate and fill new device structure.
+ * We need enough for struct device plus DPA plus the LAN API private
+ * area, which requires a minimum of 16KB. The top of the allocated
+ * area will be assigned to struct device; the next chunk will be
+ * assigned to DPA; and finally, the rest will be assigned to the
+ * the LAN API layer.
+ */
+ dev = (struct device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
+ memset(dev, 0, dev_size);
X #ifdef RCDEBUG
- printk("rc: dev = 0x%08X\n", (uint)dev);
+ printk("rc: dev = 0x%08X\n", (uint)dev);
X #endif
X
- /*
- * dev->priv will point to the start of DPA.
- */
- dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
- pDpa = dev->priv;
- dev->name = pDpa->devname;
-
- pDpa->dev = dev; /* this is just for easy reference */
- pDpa->function = function;
- pDpa->bus = bus;
- pDpa->id = card_idx; /* the device number */
- pDpa->pci_addr = memaddr;
- PCIAdapters[card_idx] = pDpa;
-#ifdef RCDEBUG
- printk("rc: pDpa = 0x%x, id = %d \n", (uint)pDpa, (uint)pDpa->id);
-#endif
-
- /*
- * Save the starting address of the LAN API private area. We'll
- * pass that to InitRCApiMsgLayer().
- */
- pDpa->PLanApiPA = (void *)(((long)pDpa + sizeof(DPA) + 0xff) & ~0xff);
+ /*
+ * dev->priv will point to the start of DPA.
+ */
+ dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
+ pDpa = dev->priv;
+ dev->name = pDpa->devname;
+
+ pDpa->dev = dev; /* this is just for easy reference */
+ pDpa->function = function;
+ pDpa->bus = bus;
+ pDpa->id = card_idx; /* the device number */
+ pDpa->pci_addr = memaddr;
+ PCIAdapters[card_idx] = pDpa;
+#ifdef RCDEBUG
+ printk("rc: pDpa = 0x%x, id = %d \n", (uint)pDpa, (uint)pDpa->id);
+#endif
+
+ /*
+ * Save the starting address of the LAN API private area. We'll
+ * pass that to RCInitI2OMsgLayer().
+ */
+ pDpa->PLanApiPA = (void *)(((long)pDpa + sizeof(DPA) + 0xff) & ~0xff);
X #ifdef RCDEBUG
- printk("rc: pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA);
+ printk("rc: pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA);
X #endif
X
- /* The adapter is accessable through memory-access read/write, not
- * I/O read/write. Thus, we need to map it to some virtual address
- * area in order to access the registers are normal memory.
- */
- vaddr = (ulong *) ioremap(memaddr, 32768);
+ /* The adapter is accessable through memory-access read/write, not
+ * I/O read/write. Thus, we need to map it to some virtual address
+ * area in order to access the registers are normal memory.
+ */
+ vaddr = (ulong *) ioremap (memaddr, 2*32768);
+#ifdef RCDEBUG
+ printk("rc: RCfound_device: 0x%x, priv = 0x%x, vaddr = 0x%x\n",
+ (uint)dev, (uint)dev->priv, (uint)vaddr);
+#endif
+ dev->base_addr = (unsigned long)vaddr;
+ dev->irq = irq;
+ dev->interrupt = 0;
+
+ /*
+ * Request a shared interrupt line.
+ */
+ if ( request_irq(dev->irq, (void *)RCinterrupt,
+ SA_INTERRUPT|SA_SHIRQ, "RedCreek VPN Adapter", dev) )
+ {
+ printk( "RC PCI 45: %s: unable to get IRQ %d\n", (PU8)dev->name, (uint)dev->irq );
+ iounmap(vaddr);
+ kfree(dev);


+ return 0;
+ }
+

+ init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr,
+ pDpa->PLanApiPA, (PU8)virt_to_bus((void *)pDpa->PLanApiPA),
+ (PFNTXCALLBACK)RCxmit_callback,
+ (PFNRXCALLBACK)RCrecv_callback,
+ (PFNCALLBACK)RCreboot_callback);
X #ifdef RCDEBUG
- printk("rc: RCfound_device: 0x%x, priv = 0x%x, vaddr = 0x%x\n",
- (uint)dev, (uint)dev->priv, (uint)vaddr);
+ printk("rc: I2O msg initted: status = 0x%x\n", init_status);
X #endif
- dev->base_addr = (unsigned long)vaddr;
- dev->irq = irq;
- dev->interrupt = 0;
+ if (init_status)
+ {
+ printk("rc: Unable to initialize msg layer\n");
+ free_irq(dev->irq, dev);
+ iounmap(vaddr);
+ kfree(dev);
+ return 0;
+ }
+ if (RCGetMAC(pDpa->id, dev->dev_addr, NULL))
+ {
+ printk("rc: Unable to get adapter MAC\n");
+ free_irq(dev->irq, dev);
+ iounmap(vaddr);
+ kfree(dev);


+ return 0;
+ }
X

- /*
- * Request a shared interrupt line.
- */
- if ( request_irq(dev->irq, (void *)RCinterrupt,
- SA_INTERRUPT|SA_SHIRQ, "RedCreek VPN Adapter", dev) )
- {
- printk( "RC PCI 45: %s: unable to get IRQ %d\n", (PU8)dev->name, (uint)dev->irq );
- iounmap(vaddr);
- kfree(dev);
- return 0;
- }
-
- init_status = InitRCApiMsgLayer(pDpa->id, dev->base_addr,
- pDpa->PLanApiPA, pDpa->PLanApiPA,
- (PFNTXCALLBACK)RCxmit_callback,
- (PFNRXCALLBACK)RCrecv_callback,
- (PFNCALLBACK)RCreboot_callback);
-#ifdef RCDEBUG
- printk("rc: msg initted: status = 0x%x\n", init_status);
-#endif
- if (init_status)
- {
- printk("rc: Unable to initialize msg layer\n");
- free_irq(dev->irq, dev);
- vfree(vaddr);
- kfree(dev);
- return 0;
- }
- if (RCGetMAC(pDpa->id, dev->dev_addr, NULL))
- {
- printk("rc: Unable to get adapter MAC\n");
- free_irq(dev->irq, dev);
- vfree(vaddr);
- kfree(dev);
- return 0;
- }
-
- DriverControlWord |= WARM_REBOOT_CAPABLE;
- RCReportDriverCapability(pDpa->id, DriverControlWord);
-
- dev->init = RCprobe1;
- ether_setup(dev); /* linux kernel interface */
-
- pDpa->next = root_RCdev;
- root_RCdev = dev;
-
- if (register_netdev(dev) != 0) /* linux kernel interface */
- {
- printk("rc: unable to register device \n");
- free_irq(dev->irq, dev);
- vfree(vaddr);
- kfree(dev);
- return 0;
- }
- return dev;
+ DriverControlWord |= WARM_REBOOT_CAPABLE;
+ RCReportDriverCapability(pDpa->id, DriverControlWord);
+
+ dev->init = RCprobe1;
+ ether_setup(dev); /* linux kernel interface */
+
+ pDpa->next = root_RCdev;
+ root_RCdev = dev;
+
+ if (register_netdev(dev) != 0) /* linux kernel interface */
+ {
+ printk("rc: unable to register device \n");
+ free_irq(dev->irq, dev);
+ iounmap(vaddr);
+ kfree(dev);
+ return 0;
+ }
+ return dev;
X }
X
X static int RCprobe1(struct device *dev)
X {
- dev->open = RCopen;
- dev->hard_start_xmit = RC_xmit_packet;
- dev->stop = RCclose;
- dev->get_stats = RCget_stats;
- dev->do_ioctl = RCioctl;
- dev->set_config = RCconfig;
- return 0;
+ dev->open = RCopen;
+ dev->hard_start_xmit = RC_xmit_packet;
+ dev->stop = RCclose;
+ dev->get_stats = RCget_stats;
+ dev->do_ioctl = RCioctl;
+ dev->set_config = RCconfig;
+ return 0;


X }
X
X static int

@@ -438,25 +448,25 @@
X #ifdef RCDEBUG
X printk("rc: RCopen\n");
X #endif
- RCEnableAdapterInterrupts(pDpa->id);
+ RCEnableI2OInterrupts(pDpa->id);
X
X if (pDpa->nexus)
X {
- /* This is not the first time RCopen is called. Thus,
- * the interface was previously opened and later closed
- * by RCclose(). RCclose() does a Shutdown; to wake up
- * the adapter, a reset is mandatory before we can post
- * receive buffers. However, if the adapter initiated
- * a reboot while the interface was closed -- and interrupts
- * were turned off -- we need will need to reinitialize
- * the adapter, rather than simply waking it up.
- */
+ /* This is not the first time RCopen is called. Thus,
+ * the interface was previously opened and later closed
+ * by RCclose(). RCclose() does a Shutdown; to wake up
+ * the adapter, a reset is mandatory before we can post
+ * receive buffers. However, if the adapter initiated
+ * a reboot while the interface was closed -- and interrupts
+ * were turned off -- we need will need to reinitialize
+ * the adapter, rather than simply waking it up.
+ */
X printk("rc: Waking up adapter...\n");
X RCResetLANCard(pDpa->id,0,0,0);
X }
X else
X {
- pDpa->nexus = 1;
+ pDpa->nexus = 1;
X }
X
X while(post_buffers)
@@ -469,19 +479,19 @@
X
X if ( count < requested )
X {
- /*
- * Check to see if we were able to post any buffers at all.
- */
- if (post_buffers == MAX_NMBR_RCV_BUFFERS)
- {
- printk("rc: Error RCopen: not able to allocate any buffers\r\n");
- return(-ENOMEM);
- }
- printk("rc: Warning RCopen: not able to allocate all requested buffers\r\n");
- break; /* we'll try to post more buffers later */
+ /*
+ * Check to see if we were able to post any buffers at all.
+ */
+ if (post_buffers == MAX_NMBR_RCV_BUFFERS)
+ {
+ printk("rc: Error RCopen: not able to allocate any buffers\r\n");
+ return(-ENOMEM);
+ }
+ printk("rc: Warning RCopen: not able to allocate all requested buffers\r\n");
+ break; /* we'll try to post more buffers later */
X }
X else
- post_buffers -= count;
+ post_buffers -= count;
X }
X pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers;
X pDpa->shutdown = 0; /* just in case */
@@ -496,68 +506,69 @@
X RC_xmit_packet(struct sk_buff *skb, struct device *dev)
X {
X
- PDPA pDpa = (PDPA) dev->priv;
- singleTCB tcb;
- psingleTCB ptcb = &tcb;
- RC_RETURN status = 0;
+ PDPA pDpa = (PDPA) dev->priv;
+ singleTCB tcb;
+ psingleTCB ptcb = &tcb;
+ RC_RETURN status = 0;
X
- if (dev->tbusy || pDpa->shutdown || pDpa->reboot)
- {
+ if (dev->tbusy || pDpa->shutdown || pDpa->reboot)
+ {
X #ifdef RCDEBUG
- printk("rc: RC_xmit_packet: tbusy!\n");
+ printk("rc: RC_xmit_packet: tbusy!\n");
X #endif
- return 1;
- }
+ return 1;
+ }
X
- if ( skb->len <= 0 )
- {
- printk("RC_xmit_packet: skb->len less than 0!\n");
- return 0;
- }
-
- /*
- * The user is free to reuse the TCB after RCSendPacket() returns, since
- * the function copies the necessary info into its own private space. Thus,
- * our TCB can be a local structure. The skb, on the other hand, will be
- * freed up in our interrupt handler.
- */
- ptcb->bcount = 1;
- /*
- * we'll get the context when the adapter interrupts us to tell us that
- * the transmision is done. At that time, we can free skb.
- */
- ptcb->b.context = (U32)skb;
- ptcb->b.scount = 1;
- ptcb->b.size = skb->len;
- ptcb->b.addr = (U32)skb->data;
-
-#ifdef RCDEBUG
- printk("rc: RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n",
- (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb);
-#endif
- if ( (status = RCSendPacket(pDpa->id, (U32)NULL, (PRCTCB)ptcb))
- != RC_RTN_NO_ERROR)
- {
-#ifdef RCDEBUG
- printk("rc: RC send error 0x%x\n", (uint)status);
-#endif
- dev->tbusy = 1;
- }
- else
- {
- dev->trans_start = jiffies;
- // dev->tbusy = 0;
- }
- /*
- * That's it!
- */
- return 0;
+ if ( skb->len <= 0 )
+ {
+ printk("RC_xmit_packet: skb->len less than 0!\n");


+ return 0;
+ }
+

+ /*
+ * The user is free to reuse the TCB after RCI2OSendPacket() returns, since
+ * the function copies the necessary info into its own private space. Thus,
+ * our TCB can be a local structure. The skb, on the other hand, will be
+ * freed up in our interrupt handler.
+ */
+ ptcb->bcount = 1;
+ /*
+ * we'll get the context when the adapter interrupts us to tell us that
+ * the transmision is done. At that time, we can free skb.
+ */
+ ptcb->b.context = (U32)skb;
+ ptcb->b.scount = 1;
+ ptcb->b.size = skb->len;
+ ptcb->b.addr = virt_to_bus((void *)skb->data);
+
+#ifdef RCDEBUG
+ printk("rc: RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n",
+ (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb);
+#endif
+ if ( (status = RCI2OSendPacket(pDpa->id, (U32)NULL, (PRCTCB)ptcb))
+ != RC_RTN_NO_ERROR)
+ {
+#ifdef RCDEBUG
+ printk("rc: RC send error 0x%x\n", (uint)status);
+#endif
+ dev->tbusy = 1;
+ return 1;
+ }
+ else
+ {
+ dev->trans_start = jiffies;
+ // dev->tbusy = 0;
+ }
+ /*
+ * That's it!
+ */


+ return 0;
X }
X

X /*
X * RCxmit_callback()
X *
- * The transmit callback routine. It's called by RCProcMsgQ()
+ * The transmit callback routine. It's called by RCProcI2OMsgQ()
X * because the adapter is done with one or more transmit buffers and
X * it's returning them to us, or we asked the adapter to return the
X * outstanding transmit buffers by calling RCResetLANCard() with
@@ -574,80 +585,84 @@
X PDPA pDpa;
X struct device *dev;
X
- pDpa = PCIAdapters[AdapterID];
- if (!pDpa)
- {
- printk("rc: Fatal error: xmit callback, !pDpa\n");
- return;
- }
- dev = pDpa->dev;
+ pDpa = PCIAdapters[AdapterID];
+ if (!pDpa)
+ {
+ printk("rc: Fatal error: xmit callback, !pDpa\n");
+ return;
+ }
+ dev = pDpa->dev;
X
X // printk("xmit_callback: Status = 0x%x\n", (uint)Status);
- if (Status != RC_REPLY_STATUS_SUCCESS)
- {
- printk("rc: xmit_callback: Status = 0x%x\n", (uint)Status);
- }
+ if (Status != I2O_REPLY_STATUS_SUCCESS)
+ {
+ printk("rc: xmit_callback: Status = 0x%x\n", (uint)Status);
+ }
X #ifdef RCDEBUG
- if (pDpa->shutdown || pDpa->reboot)
- printk("rc: xmit callback: shutdown||reboot\n");
+ if (pDpa->shutdown || pDpa->reboot)
+ printk("rc: xmit callback: shutdown||reboot\n");
X #endif
X
X #ifdef RCDEBUG
- printk("rc: xmit_callback: PcktCount = %d, BC = 0x%x\n",
- (uint)PcktCount, (uint)BufferContext);
+ printk("rc: xmit_callback: PcktCount = %d, BC = 0x%x\n",
+ (uint)PcktCount, (uint)BufferContext);
X #endif
- while (PcktCount--)
- {
- skb = (struct sk_buff *)(BufferContext[0]);
+ while (PcktCount--)
+ {
+ skb = (struct sk_buff *)(BufferContext[0]);
X #ifdef RCDEBUG
- printk("rc: skb = 0x%x\n", (uint)skb);
+ printk("rc: skb = 0x%x\n", (uint)skb);
X #endif
- BufferContext++;
- dev_kfree_skb(skb);
- }
- dev->tbusy = 0;
+ BufferContext++;
+#ifdef LINUX_2_1
+ dev_kfree_skb (skb);
+#else


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 09'
echo 'File patch-2.2.0-pre8 is continued in part 10'
echo 10 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part10

#!/bin/sh
# this is part 10 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 10; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

+ dev_kfree_skb (skb, FREE_WRITE);
+#endif
+ }
+ dev->tbusy = 0;
X

X }
X
X static void

X RCreset_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
X {
- PDPA pDpa;
- struct device *dev;
+ PDPA pDpa;


+ struct device *dev;
X

- pDpa = PCIAdapters[AdapterID];

- dev = pDpa->dev;
+ pDpa = PCIAdapters[AdapterID];

+ dev = pDpa->dev;

X #ifdef RCDEBUG
- printk("rc: RCreset_callback Status 0x%x\n", (uint)Status);
+ printk("rc: RCreset_callback Status 0x%x\n", (uint)Status);
X #endif
- /*
- * Check to see why we were called.
- */
- if (pDpa->shutdown)
- {
- printk("rc: Shutting down interface\n");
- pDpa->shutdown = 0;
- pDpa->reboot = 0;
- MOD_DEC_USE_COUNT;
- }
- else if (pDpa->reboot)
- {
- printk("rc: reboot, shutdown adapter\n");
- /*
- * We don't set any of the flags in RCShutdownLANCard()
- * and we don't pass a callback routine to it.
- * The adapter will have already initiated the reboot by
- * the time the function returns.
- */
- RCDisableAdapterInterrupts(pDpa->id);
- RCShutdownLANCard(pDpa->id,0,0,0);
- printk("rc: scheduling timer...\n");
- init_timer(&pDpa->timer);
- pDpa->timer.expires = RUN_AT((30*HZ)/10); /* 3 sec. */
- pDpa->timer.data = (unsigned long)dev;
- pDpa->timer.function = &rc_timer; /* timer handler */
- add_timer(&pDpa->timer);
- }
+ /*
+ * Check to see why we were called.
+ */
+ if (pDpa->shutdown)
+ {
+ printk("rc: Shutting down interface\n");
+ pDpa->shutdown = 0;
+ pDpa->reboot = 0;
+ MOD_DEC_USE_COUNT;
+ }
+ else if (pDpa->reboot)
+ {
+ printk("rc: reboot, shutdown adapter\n");
+ /*
+ * We don't set any of the flags in RCShutdownLANCard()
+ * and we don't pass a callback routine to it.
+ * The adapter will have already initiated the reboot by
+ * the time the function returns.
+ */
+ RCDisableI2OInterrupts(pDpa->id);
+ RCShutdownLANCard(pDpa->id,0,0,0);
+ printk("rc: scheduling timer...\n");
+ init_timer(&pDpa->timer);
+ pDpa->timer.expires = RUN_AT((30*HZ)/10); /* 3 sec. */
+ pDpa->timer.data = (unsigned long)dev;
+ pDpa->timer.function = &rc_timer; /* timer handler */
+ add_timer(&pDpa->timer);
+ }
X
X
X
@@ -656,33 +671,33 @@
X static void
X RCreboot_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
X {
- PDPA pDpa;
+ PDPA pDpa;


X
- pDpa = PCIAdapters[AdapterID];

+ pDpa = PCIAdapters[AdapterID];

X #ifdef RCDEBUG
- printk("rc: RCreboot: rcv buffers outstanding = %d\n",
- (uint)pDpa->numOutRcvBuffers);
+ printk("rc: RCreboot: rcv buffers outstanding = %d\n",
+ (uint)pDpa->numOutRcvBuffers);
X #endif
- if (pDpa->shutdown)
- {
- printk("rc: skipping reboot sequence -- shutdown already initiated\n");
- return;
- }
- pDpa->reboot = 1;
- /*
- * OK, we reset the adapter and ask it to return all
- * outstanding transmit buffers as well as the posted
- * receive buffers. When the adapter is done returning
- * those buffers, it will call our RCreset_callback()
- * routine. In that routine, we'll call RCShutdownLANCard()
- * to tell the adapter that it's OK to start the reboot and
- * schedule a timer callback routine to execute 3 seconds
- * later; this routine will reinitialize the adapter at that time.
- */
- RCResetLANCard(pDpa->id,
- RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |
- RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
- (PFNCALLBACK)RCreset_callback);
+ if (pDpa->shutdown)
+ {
+ printk("rc: skipping reboot sequence -- shutdown already initiated\n");
+ return;
+ }
+ pDpa->reboot = 1;
+ /*
+ * OK, we reset the adapter and ask it to return all
+ * outstanding transmit buffers as well as the posted
+ * receive buffers. When the adapter is done returning
+ * those buffers, it will call our RCreset_callback()
+ * routine. In that routine, we'll call RCShutdownLANCard()
+ * to tell the adapter that it's OK to start the reboot and
+ * schedule a timer callback routine to execute 3 seconds
+ * later; this routine will reinitialize the adapter at that time.
+ */
+ RCResetLANCard(pDpa->id,
+ RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |
+ RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
+ (PFNCALLBACK)RCreset_callback);
X }
X
X
@@ -699,7 +714,7 @@
X * RCrecv_callback()
X *
X * The receive packet callback routine. This is called by
- * RCProcMsgQ() after the adapter posts buffers which have been
+ * RCProcI2OMsgQ() after the adapter posts buffers which have been
X * filled (one ethernet packet per buffer).


X */
X static void

@@ -710,131 +725,144 @@
X U16 AdapterID)
X {
X
- U32 len, count;
- PDPA pDpa;
- struct sk_buff *skb;
- struct device *dev;


- singleTCB tcb;
- psingleTCB ptcb = &tcb;

+ U32 len, count;
+ PDPA pDpa;
+ struct sk_buff *skb;
+ struct device *dev;


+ singleTCB tcb;
+ psingleTCB ptcb = &tcb;

X

X
- pDpa = PCIAdapters[AdapterID];

- dev = pDpa->dev;
+ pDpa = PCIAdapters[AdapterID];

+ dev = pDpa->dev;
X

- ptcb->bcount = 1;

+ ptcb->bcount = 1;

X
X #ifdef RCDEBUG
- printk("rc: RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
- (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock);
+ printk("rc: RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
+ (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock);


X #endif
X
X #ifdef RCDEBUG

- if ((pDpa->shutdown || pDpa->reboot) && !Status)
- printk("shutdown||reboot && !Status: PktCount = %d\n",PktCount);
+ if ((pDpa->shutdown || pDpa->reboot) && !Status)
+ printk("shutdown||reboot && !Status: PktCount = %d\n",PktCount);
X #endif
X
- if ( (Status != RC_REPLY_STATUS_SUCCESS) || pDpa->shutdown)
- {
- /*
- * Free whatever buffers the adapter returned, but don't
- * pass them to the kernel.
- */
+ if ( (Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown)
+ {
+ /*
+ * Free whatever buffers the adapter returned, but don't
+ * pass them to the kernel.
+ */
X
- if (!pDpa->shutdown && !pDpa->reboot)
- printk("rc: RCrecv error: status = 0x%x\n", (uint)Status);
- else
- printk("rc: Returning %d buffers, status = 0x%x\n",
- PktCount, (uint)Status);
- /*
- * TO DO: check the nature of the failure and put the adapter in
- * failed mode if it's a hard failure. Send a reset to the adapter
- * and free all outstanding memory.
- */
- if (Status == RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER)
- {
-#ifdef RCDEBUG
- printk("RCrecv status ABORT NO DATA TRANSFER\n");
-#endif
- }
- /* check for reset status: RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */
- if (PacketDescBlock)
- {
- while(PktCount--)
- {
- skb = (struct sk_buff *)PacketDescBlock[0];
+ if (!pDpa->shutdown && !pDpa->reboot)
+ printk("rc: RCrecv error: status = 0x%x\n", (uint)Status);
+ else
+ printk("rc: Returning %d buffers, status = 0x%x\n",
+ PktCount, (uint)Status);
+ /*
+ * TO DO: check the nature of the failure and put the adapter in
+ * failed mode if it's a hard failure. Send a reset to the adapter
+ * and free all outstanding memory.
+ */
+ if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER)
+ {
X #ifdef RCDEBUG
- printk("free skb 0x%p\n", skb);
+ printk("RCrecv status ABORT NO DATA TRANSFER\n");
X #endif
- dev_kfree_skb(skb);
- pDpa->numOutRcvBuffers--;
- PacketDescBlock += BD_SIZE; /* point to next context field */
- }
- }
- return;
- }
- else
- {
- while(PktCount--)
- {
+ }
+ /* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */
+ if (PacketDescBlock)
+ {
+ while(PktCount--)
+ {
X skb = (struct sk_buff *)PacketDescBlock[0];
+#ifndef LINUX_2_1
+ skb->free = 1;
+ skb->lock = 0;
+#endif
X #ifdef RCDEBUG
- if (pDpa->shutdown)
- printk("shutdown: skb=0x%x\n", (uint)skb);
-
- printk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb,
- (uint)skb->data[0], (uint)skb->data[1], (uint)skb->data[2],
- (uint)skb->data[3], (uint)skb->data[4], (uint)skb->data[5]);
+ printk("free skb 0x%p\n", skb);
X #endif
- if ( (memcmp(dev->dev_addr, skb->data, 6)) &&
- (!broadcast_packet(skb->data)))


+#ifdef LINUX_2_1
+ dev_kfree_skb (skb);
+#else

+ dev_kfree_skb(skb, FREE_READ);
+#endif
+ pDpa->numOutRcvBuffers--;
+ PacketDescBlock += BD_SIZE; /* point to next context field */
+ }
+ }
+ return;
+ }
+ else
+ {
+ while(PktCount--)
+ {
+ skb = (struct sk_buff *)PacketDescBlock[0];
+#ifdef RCDEBUG
+ if (pDpa->shutdown)
+ printk("shutdown: skb=0x%x\n", (uint)skb);
+
+ printk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb,
+ (uint)skb->data[0], (uint)skb->data[1], (uint)skb->data[2],
+ (uint)skb->data[3], (uint)skb->data[4], (uint)skb->data[5]);
+#endif
+ if ( (memcmp(dev->dev_addr, skb->data, 6)) &&
+ (!broadcast_packet(skb->data)))
+ {
+ /*
+ * Re-post the buffer to the adapter. Since the adapter usually
+ * return 1 to 2 receive buffers at a time, it's not too inefficient
+ * post one buffer at a time but ... may be that should be
+ * optimized at some point.


+ */
+ ptcb->b.context = (U32)skb;
+ ptcb->b.scount = 1;

+ ptcb->b.size = MAX_ETHER_SIZE;


+ ptcb->b.addr = virt_to_bus((void *)skb->data);
+

+ if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
X {
- /*
- * Re-post the buffer to the adapter. Since the adapter usually
- * return 1 to 2 receive buffers at a time, it's not too inefficient
- * post one buffer at a time but ... may be that should be
- * optimized at some point.


- */
- ptcb->b.context = (U32)skb;
- ptcb->b.scount = 1;

- ptcb->b.size = MAX_ETHER_SIZE;


- ptcb->b.addr = (U32)skb->data;
-

- if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
- {
- printk("rc: RCrecv_callback: post buffer failed!\n");
- dev_kfree_skb(skb);
- }
- else
- {
- pDpa->numOutRcvBuffers++;
- }
+ printk("rc: RCrecv_callback: post buffer failed!\n");


+#ifdef LINUX_2_1
+ dev_kfree_skb (skb);
+#else

+ skb->free = 1;
+ dev_kfree_skb(skb, FREE_READ);
+#endif
X }
X else
X {
- len = PacketDescBlock[2];
- skb->dev = dev;
- skb_put( skb, len ); /* adjust length and tail */
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb); /* send the packet to the kernel */
- dev->last_rx = jiffies;
+ pDpa->numOutRcvBuffers++;
X }
- pDpa->numOutRcvBuffers--;
- PacketDescBlock += BD_SIZE; /* point to next context field */
- }
- }
+ }
+ else
+ {
+ len = PacketDescBlock[2];
+ skb->dev = dev;
+ skb_put( skb, len ); /* adjust length and tail */
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb); /* send the packet to the kernel */
+ dev->last_rx = jiffies;
+ }
+ pDpa->numOutRcvBuffers--;
+ PacketDescBlock += BD_SIZE; /* point to next context field */
+ }
+ }
X
- /*
- * Replenish the posted receive buffers.
- * DO NOT replenish buffers if the driver has already
- * initiated a reboot or shutdown!
- */
-
- if (!pDpa->shutdown && !pDpa->reboot)
- {
- count = RC_allocate_and_post_buffers(dev,
- MAX_NMBR_RCV_BUFFERS-pDpa->numOutRcvBuffers);
- pDpa->numOutRcvBuffers += count;
- }
+ /*
+ * Replenish the posted receive buffers.
+ * DO NOT replenish buffers if the driver has already
+ * initiated a reboot or shutdown!
+ */
+
+ if (!pDpa->shutdown && !pDpa->reboot)
+ {
+ count = RC_allocate_and_post_buffers(dev,
+ MAX_NMBR_RCV_BUFFERS-pDpa->numOutRcvBuffers);
+ pDpa->numOutRcvBuffers += count;
+ }
X
X }
X
@@ -843,156 +871,156 @@
X *
X * Interrupt handler.
X * This routine sets up a couple of pointers and calls
- * RCProcMsgQ(), which in turn process the message and
+ * RCProcI2OMsgQ(), which in turn process the message and
X * calls one of our callback functions.


X */
X static void

X RCinterrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
X
- PDPA pDpa;
- struct device *dev = (struct device *)(dev_id);
+ PDPA pDpa;
+ struct device *dev = (struct device *)(dev_id);
X
- pDpa = (PDPA) (dev->priv);
+ pDpa = (PDPA) (dev->priv);
X
- if (pDpa->shutdown)
- printk("rc: shutdown: service irq\n");
+ if (pDpa->shutdown)
+ printk("rc: shutdown: service irq\n");
X
X #ifdef RCDEBUG
- printk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n",
- (uint)pDpa, (uint)dev, (uint)pDpa->id);
- printk("dev = 0x%x\n", (uint)dev);
+ printk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n",
+ (uint)pDpa, (uint)dev, (uint)pDpa->id);
+ printk("dev = 0x%x\n", (uint)dev);
X #endif
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
- dev->interrupt = 1;
+ if (dev->interrupt)
+ printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ dev->interrupt = 1;
X
- RCProcMsgQ(pDpa->id);


- dev->interrupt = 0;

+ RCProcI2OMsgQ(pDpa->id);


+ dev->interrupt = 0;

X
- return;
+ return;
X }
X
X #define REBOOT_REINIT_RETRY_LIMIT 10
X static void rc_timer(unsigned long data)
X {
- struct device *dev = (struct device *)data;
- PDPA pDpa = (PDPA) (dev->priv);
- int init_status;
- static int retry = 0;
- int post_buffers = MAX_NMBR_RCV_BUFFERS;
- int count = 0;
- int requested = 0;
-
- if (pDpa->reboot)


- {
-
- init_status = InitRCApiMsgLayer(pDpa->id, dev->base_addr,
- pDpa->PLanApiPA, pDpa->PLanApiPA,
- (PFNTXCALLBACK)RCxmit_callback,
- (PFNRXCALLBACK)RCrecv_callback,
- (PFNCALLBACK)RCreboot_callback);
-

- switch(init_status)
- {
- case RC_RTN_NO_ERROR:
+ struct device *dev = (struct device *)data;
+ PDPA pDpa = (PDPA) (dev->priv);
+ int init_status;
+ static int retry = 0;
+ int post_buffers = MAX_NMBR_RCV_BUFFERS;
+ int count = 0;
+ int requested = 0;
+
+ if (pDpa->reboot)


+ {
+
+ init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr,

+ pDpa->PLanApiPA, pDpa->PLanApiPA,


+ (PFNTXCALLBACK)RCxmit_callback,
+ (PFNRXCALLBACK)RCrecv_callback,
+ (PFNCALLBACK)RCreboot_callback);

+
+ switch(init_status)
+ {
+ case RC_RTN_NO_ERROR:
X
- pDpa->reboot = 0;
- pDpa->shutdown = 0; /* just in case */
- RCReportDriverCapability(pDpa->id, DriverControlWord);
- RCEnableAdapterInterrupts(pDpa->id);
-
- if (dev->flags & IFF_UP)
- {
- while(post_buffers)
- {
- if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
- requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
- else
- requested = post_buffers;
- count = RC_allocate_and_post_buffers(dev, requested);
- post_buffers -= count;
- if ( count < requested )
- break;
- }
- pDpa->numOutRcvBuffers =
- MAX_NMBR_RCV_BUFFERS - post_buffers;
- printk("rc: posted %d buffers \r\n",
- (uint)pDpa->numOutRcvBuffers);
- }
- printk("rc: Initialization done.\n");
- return;
- case RC_RTN_FREE_Q_EMPTY:
- retry++;
- printk("rc: inbound free q emtpy\n");
- break;
- default:
- retry++;
- printk("rc: unexpected bad status after reboot\n");
- break;
- }
-
- if (retry > REBOOT_REINIT_RETRY_LIMIT)
- {
- printk("rc: unable to reinitialize adapter after reboot\n");
- printk("rc: decrementing driver and closing interface\n");
- RCDisableAdapterInterrupts(pDpa->id);
- dev->flags &= ~IFF_UP;
- MOD_DEC_USE_COUNT;
- }
- else
- {
- printk("rc: rescheduling timer...\n");
- init_timer(&pDpa->timer);
- pDpa->timer.expires = RUN_AT((30*HZ)/10); /* 3 sec. */
- pDpa->timer.data = (unsigned long)dev;
- pDpa->timer.function = &rc_timer; /* timer handler */
- add_timer(&pDpa->timer);
- }
- }
- else
- {
- printk("rc: timer??\n");
- }
+ pDpa->reboot = 0;
+ pDpa->shutdown = 0; /* just in case */
+ RCReportDriverCapability(pDpa->id, DriverControlWord);
+ RCEnableI2OInterrupts(pDpa->id);
+
+ if (dev->flags & IFF_UP)
+ {
+ while(post_buffers)
+ {
+ if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+ requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
+ else
+ requested = post_buffers;
+ count = RC_allocate_and_post_buffers(dev, requested);
+ post_buffers -= count;
+ if ( count < requested )
+ break;
+ }
+ pDpa->numOutRcvBuffers =
+ MAX_NMBR_RCV_BUFFERS - post_buffers;
+ printk("rc: posted %d buffers \r\n",
+ (uint)pDpa->numOutRcvBuffers);
+ }
+ printk("rc: Initialization done.\n");
+ return;
+ case RC_RTN_FREE_Q_EMPTY:
+ retry++;
+ printk("rc: inbound free q emtpy\n");
+ break;
+ default:
+ retry++;
+ printk("rc: unexpected bad status after reboot\n");
+ break;
+ }
+
+ if (retry > REBOOT_REINIT_RETRY_LIMIT)
+ {
+ printk("rc: unable to reinitialize adapter after reboot\n");
+ printk("rc: decrementing driver and closing interface\n");
+ RCDisableI2OInterrupts(pDpa->id);
+ dev->flags &= ~IFF_UP;
+ MOD_DEC_USE_COUNT;
+ }
+ else
+ {
+ printk("rc: rescheduling timer...\n");
+ init_timer(&pDpa->timer);
+ pDpa->timer.expires = RUN_AT((30*HZ)/10); /* 3 sec. */
+ pDpa->timer.data = (unsigned long)dev;
+ pDpa->timer.function = &rc_timer; /* timer handler */
+ add_timer(&pDpa->timer);
+ }
+ }
+ else
+ {
+ printk("rc: timer??\n");
+ }


X }
X
X static int

X RCclose(struct device *dev)


X {
X
- PDPA pDpa = (PDPA) dev->priv;

+ PDPA pDpa = (PDPA) dev->priv;

X
X #ifdef RCDEBUG
- printk("rc: RCclose\r\n");
+ printk("rc: RCclose\r\n");
X #endif
- if (pDpa->reboot)
- {
- printk("rc: skipping reset -- adapter already in reboot mode\n");
- dev->flags &= ~IFF_UP;
- pDpa->shutdown = 1;
- return 0;
- }
+ if (pDpa->reboot)
+ {
+ printk("rc: skipping reset -- adapter already in reboot mode\n");
+ dev->flags &= ~IFF_UP;
+ pDpa->shutdown = 1;
+ return 0;
+ }
X #ifdef RCDEBUG
- printk("rc: receive buffers outstanding: %d\n",
- (uint)pDpa->numOutRcvBuffers);
+ printk("rc: receive buffers outstanding: %d\n",
+ (uint)pDpa->numOutRcvBuffers);
X #endif
X
- pDpa->shutdown = 1;
+ pDpa->shutdown = 1;
X
- /*
- * We can't allow the driver to be unloaded until the adapter returns
- * all posted receive buffers. It doesn't hurt to tell the adapter
- * to return all posted receive buffers and outstanding xmit buffers,
- * even if there are none.
- */
+ /*
+ * We can't allow the driver to be unloaded until the adapter returns
+ * all posted receive buffers. It doesn't hurt to tell the adapter
+ * to return all posted receive buffers and outstanding xmit buffers,
+ * even if there are none.
+ */
X
- RCShutdownLANCard(pDpa->id,
- RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |
- RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
- (PFNCALLBACK)RCreset_callback);
+ RCShutdownLANCard(pDpa->id,
+ RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |
+ RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
+ (PFNCALLBACK)RCreset_callback);
X
- dev->flags &= ~IFF_UP;
- return 0;
+ dev->flags &= ~IFF_UP;


+ return 0;
X }
X

X static struct enet_statistics *
@@ -1094,230 +1122,298 @@


X
X switch (cmd) {
X

- case RCU_PROTOCOL_REV:
- /*
- * Assign user protocol revision, to tell user-level
- * controller program whether or not it's in sync.
- */
- rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV;
- break;
+ case RCU_PROTOCOL_REV:
+ /*
+ * Assign user protocol revision, to tell user-level
+ * controller program whether or not it's in sync.
+ */
+ rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV;
+ break;
X
X
- case RCU_COMMAND:
- {
- if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
- return -EFAULT;
+ case RCU_COMMAND:
+ {
+#ifdef LINUX_2_1
+ if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
+ return -EFAULT;
+#else
+ int error;
+ error=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(RCuser));
+ if (error) {
+ return error;
+ }
+ memcpy_fromfs(&RCuser, rq->ifr_data, sizeof(RCuser));
+#endif
X
X #ifdef RCDEBUG
- printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
+ printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
X #endif
X
- switch(RCuser.cmd)
+ switch(RCuser.cmd)
+ {
+ case RCUC_GETFWVER:
+ printk("RC GETFWVER\n");
+ RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
+ RCGetFirmwareVer(pDpa->id, (PU8) &RCUD_GETFWVER->FirmString, NULL);
+ break;
+ case RCUC_GETINFO:
+ printk("RC GETINFO\n");
+ RCUD_GETINFO = &RCuser.RCUS_GETINFO;
+ RCUD_GETINFO -> mem_start = dev->base_addr;
+ RCUD_GETINFO -> mem_end = dev->base_addr + 2*32768;
+ RCUD_GETINFO -> base_addr = pDpa->pci_addr;
+ RCUD_GETINFO -> irq = dev->irq;
+ break;
+ case RCUC_GETIPANDMASK:
+ printk("RC GETIPANDMASK\n");
+ RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
+ RCGetRavlinIPandMask(pDpa->id, (PU32) &RCUD_GETIPANDMASK->IpAddr,
+ (PU32) &RCUD_GETIPANDMASK->NetMask, NULL);
+ break;
+ case RCUC_GETLINKSTATISTICS:
+ printk("RC GETLINKSTATISTICS\n");
+ RCUD_GETLINKSTATISTICS = &RCuser.RCUS_GETLINKSTATISTICS;
+ RCGetLinkStatistics(pDpa->id, (P_RCLINKSTATS) &RCUD_GETLINKSTATISTICS->StatsReturn, NULL);
+ break;
+ case RCUC_GETLINKSTATUS:
+ printk("RC GETLINKSTATUS\n");
+ RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
+ RCGetLinkStatus(pDpa->id, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
+ break;
+ case RCUC_GETMAC:
+ printk("RC GETMAC\n");
+ RCUD_GETMAC = &RCuser.RCUS_GETMAC;
+ RCGetMAC(pDpa->id, (PU8) &RCUD_GETMAC->mac, NULL);
+ break;
+ case RCUC_GETPROM:
+ printk("RC GETPROM\n");
+ RCUD_GETPROM = &RCuser.RCUS_GETPROM;
+ RCGetPromiscuousMode(pDpa->id, (PU32) &RCUD_GETPROM->PromMode, NULL);
+ break;
+ case RCUC_GETBROADCAST:
+ printk("RC GETBROADCAST\n");
+ RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST;
+ RCGetBroadcastMode(pDpa->id, (PU32) &RCUD_GETBROADCAST->BroadcastMode, NULL);
+ break;
+ case RCUC_GETSPEED:
+ printk("RC GETSPEED\n");
+ if (!(dev->flags & IFF_UP))
X {
- case RCUC_GETFWVER:
- printk("RC GETFWVER\n");
- RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
- RCGetFirmwareVer(pDpa->id, (PU8) &RCUD_GETFWVER->FirmString, NULL);
- break;
- case RCUC_GETINFO:
- printk("RC GETINFO\n");
- RCUD_GETINFO = &RCuser.RCUS_GETINFO;
- RCUD_GETINFO -> mem_start = dev->base_addr;
- RCUD_GETINFO -> mem_end = dev->base_addr + 32768;
- RCUD_GETINFO -> base_addr = pDpa->pci_addr;
- RCUD_GETINFO -> irq = dev->irq;
- break;
- case RCUC_GETIPANDMASK:
- printk("RC GETIPANDMASK\n");
- RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
- RCGetRavlinIPandMask(pDpa->id, (PU32) &RCUD_GETIPANDMASK->IpAddr,
- (PU32) &RCUD_GETIPANDMASK->NetMask, NULL);
- break;
- case RCUC_GETLINKSTATISTICS:
- printk("RC GETLINKSTATISTICS\n");
- RCUD_GETLINKSTATISTICS = &RCuser.RCUS_GETLINKSTATISTICS;
- RCGetLinkStatistics(pDpa->id, (P_RCLINKSTATS) &RCUD_GETLINKSTATISTICS->StatsReturn, NULL);
- break;
- case RCUC_GETLINKSTATUS:
- printk("RC GETLINKSTATUS\n");
- RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
- RCGetLinkStatus(pDpa->id, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
- break;
- case RCUC_GETMAC:
- printk("RC GETMAC\n");
- RCUD_GETMAC = &RCuser.RCUS_GETMAC;
- RCGetMAC(pDpa->id, (PU8) &RCUD_GETMAC->mac, NULL);
- break;
- case RCUC_GETSPEED:
- printk("RC GETSPEED\n");
- if (!(dev->flags & IFF_UP))
- {
- printk("RCioctl, GETSPEED error: interface down\n");
- return -ENODATA;
- }
- RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
- RCGetLinkSpeed(pDpa->id, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL);
- printk("RC speed = 0x%ld\n", RCUD_GETSPEED->LinkSpeedCode);
- break;
- default:
- printk("RC command default\n");
- RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;
- RCUD_DEFAULT -> rc = 0x11223344;
- break;
+ printk("RCioctl, GETSPEED error: interface down\n");
+ return -ENODATA;
X }
- copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
+ RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
+ RCGetLinkSpeed(pDpa->id, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL);
+ printk("RC speed = 0x%ld\n", RCUD_GETSPEED->LinkSpeedCode);
+ break;
+ case RCUC_SETIPANDMASK:
+ printk("RC SETIPANDMASK\n");
+ RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK;
+ printk ("RC New IP Addr = %d.%d.%d.%d, ", (U8) ((RCUD_SETIPANDMASK->IpAddr) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->IpAddr >> 8) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->IpAddr >> 16) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->IpAddr >> 24) & 0xff));
+ printk ("RC New Mask = %d.%d.%d.%d\n", (U8) ((RCUD_SETIPANDMASK->NetMask) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->NetMask >> 8) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->NetMask >> 16) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->NetMask >> 24) & 0xff));
+ RCSetRavlinIPandMask(pDpa->id, (U32) RCUD_SETIPANDMASK->IpAddr,
+ (U32) RCUD_SETIPANDMASK->NetMask);
+ break;
+ case RCUC_SETMAC:
+ printk("RC SETMAC\n");
+ RCUD_SETMAC = &RCuser.RCUS_SETMAC;
+ printk ("RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+ (U8) (RCUD_SETMAC->mac[0]), (U8) (RCUD_SETMAC->mac[1]), (U8) (RCUD_SETMAC->mac[2]),
+ (U8) (RCUD_SETMAC->mac[3]), (U8) (RCUD_SETMAC->mac[4]), (U8) (RCUD_SETMAC->mac[5]));
+ RCSetMAC(pDpa->id, (PU8) &RCUD_SETMAC->mac);
+ break;
+ case RCUC_SETSPEED:
+ printk("RC SETSPEED\n");
+ RCUD_SETSPEED = &RCuser.RCUS_SETSPEED;
+ RCSetLinkSpeed(pDpa->id, (U16) RCUD_SETSPEED->LinkSpeedCode);
+ printk("RC New speed = 0x%d\n", RCUD_SETSPEED->LinkSpeedCode);
+ break;
+ case RCUC_SETPROM:
+ printk("RC SETPROM\n");
+ RCUD_SETPROM = &RCuser.RCUS_SETPROM;
+ RCSetPromiscuousMode(pDpa->id,(U16)RCUD_SETPROM->PromMode);
+ printk("RC New prom mode = 0x%d\n", RCUD_SETPROM->PromMode);
+ break;
+ case RCUC_SETBROADCAST:
+ printk("RC SETBROADCAST\n");
+ RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST;
+ RCSetBroadcastMode(pDpa->id,(U16)RCUD_SETBROADCAST->BroadcastMode);
+ printk("RC New broadcast mode = 0x%d\n", RCUD_SETBROADCAST->BroadcastMode);
X break;
- } /* RCU_COMMAND */
-
X default:
- printk("RC default\n");
- rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678;
+ printk("RC command default\n");
+ RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;
+ RCUD_DEFAULT -> rc = 0x11223344;
X break;
+ }
+#ifdef LINUX_2_1
+ copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
+#else
+ memcpy_tofs(rq->ifr_data, &RCuser, sizeof(RCuser));
+#endif
+ break;
+ } /* RCU_COMMAND */
+
+ default:
+ printk("RC default\n");
+ rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678;
+ break;
X }
X return 0;
X }
X
X static int RCconfig(struct device *dev, struct ifmap *map)
X {
- /*
- * To be completed ...
+ /*
+ * To be completed ...
X */
- printk("rc: RCconfig\n");
- return 0;
- if (dev->flags & IFF_UP) /* can't act on a running interface */
- return -EBUSY;
+ printk("rc: RCconfig\n");
+ return 0;
+ if (dev->flags & IFF_UP) /* can't act on a running interface */
+ return -EBUSY;
X
X /* Don't allow changing the I/O address */
- if (map->base_addr != dev->base_addr) {
- printk(KERN_WARNING "RC pci45: Change I/O address not implemented\n");
- return -EOPNOTSUPP;
- }
- return 0;
+ if (map->base_addr != dev->base_addr) {
+ printk(KERN_WARNING "RC pci45: Change I/O address not implemented\n");
+ return -EOPNOTSUPP;
+ }


+ return 0;
X }
X

-#ifdef MODULE
-void cleanup_module(void)
+void
+cleanup_module(void)
X {
- PDPA pDpa;
- struct device *next;
+ PDPA pDpa;
+ struct device *next;
X
X
X #ifdef RCDEBUG
- printk("rc: RC cleanup_module\n");
- printk("rc: root_RCdev = 0x%x\n", (uint)root_RCdev);
+ printk("rc: RC cleanup_module\n");
+ printk("rc: root_RCdev = 0x%x\n", (uint)root_RCdev);
X #endif
X
X
- while (root_RCdev)
- {
- pDpa = (PDPA) root_RCdev->priv;
+ while (root_RCdev)
+ {
+ pDpa = (PDPA) root_RCdev->priv;
X #ifdef RCDEBUG
- printk("rc: cleanup 0x%08X\n", (uint)root_RCdev);
+ printk("rc: cleanup 0x%08X\n", (uint)root_RCdev);
X #endif
- printk("Adapter reset: 0x%x\n", RCResetAdapter(pDpa->id));
- unregister_netdev(root_RCdev);
- next = pDpa->next;
-
- vfree((unsigned long *)root_RCdev->base_addr);
- free_irq( root_RCdev->irq, root_RCdev );
- kfree(root_RCdev);
- root_RCdev = next;
- }
+ printk("IOP reset: 0x%x\n", RCResetIOP(pDpa->id));
+ unregister_netdev(root_RCdev);
+ next = pDpa->next;
+
+ iounmap((unsigned long *)root_RCdev->base_addr);
+ free_irq( root_RCdev->irq, root_RCdev );
+ kfree(root_RCdev);
+ root_RCdev = next;
+ }
X }
-#endif
-
X
X static int
X RC_allocate_and_post_buffers(struct device *dev, int numBuffers)
X {
X
- int i;
- PDPA pDpa = (PDPA)dev->priv;
- PU32 p;
- psingleB pB;
- struct sk_buff *skb;
- RC_RETURN status;
-
- if (!numBuffers)
- return 0;
- else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
- {
+ int i;
+ PDPA pDpa = (PDPA)dev->priv;
+ PU32 p;
+ psingleB pB;
+ struct sk_buff *skb;
+ RC_RETURN status;
+
+ if (!numBuffers)
+ return 0;
+ else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+ {
X #ifdef RCDEBUG
- printk("rc: Too many buffers requested!\n");
- printk("rc: attempting to allocate only 32 buffers\n");
+ printk("rc: Too many buffers requested!\n");
+ printk("rc: attempting to allocate only 32 buffers\n");
X #endif
- numBuffers = 32;
- }
+ numBuffers = 32;
+ }
X
- p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_ATOMIC);
+ p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_ATOMIC);
X
X #ifdef RCDEBUG
- printk("rc: TCB = 0x%x\n", (uint)p);
+ printk("rc: TCB = 0x%x\n", (uint)p);
X #endif
X
- if (!p)
- {
- printk("rc: RCopen: unable to allocate TCB\n");
- return 0;
- }
+ if (!p)
+ {
+ printk("rc: RCopen: unable to allocate TCB\n");
+ return 0;
+ }
X
- p[0] = 0; /* Buffer Count */
- pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
+ p[0] = 0; /* Buffer Count */
+ pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
X
X #ifdef RCDEBUG
- printk("rc: p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB);
- printk("rc: pB = 0x%x\n", (uint)pB);
+ printk("rc: p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB);
+ printk("rc: pB = 0x%x\n", (uint)pB);
X #endif
X
- for (i=0; i<numBuffers; i++)
- {
- skb = dev_alloc_skb(MAX_ETHER_SIZE+2);
- if (!skb)
- {
- printk("rc: Doh! RCopen: unable to allocate enough skbs!\n");
- if (*p != 0) /* did we allocate any buffers at all? */
- {
+ for (i=0; i<numBuffers; i++)
+ {
+ skb = dev_alloc_skb(MAX_ETHER_SIZE+2);
+ if (!skb)
+ {
+ printk("rc: Doh! RCopen: unable to allocate enough skbs!\n");
+ if (*p != 0) /* did we allocate any buffers at all? */
+ {
X #ifdef RCDEBUG
- printk("rc: will post only %d buffers \n", (uint)(*p));
+ printk("rc: will post only %d buffers \n", (uint)(*p));
X #endif
- break;
- }
- else
- {
- kfree(p); /* Free the TCB */


- return 0;
- }
- }

+ break;
+ }
+ else
+ {
+ kfree(p); /* Free the TCB */


+ return 0;
+ }
+ }

X #ifdef RCDEBUG
- printk("post 0x%x\n", (uint)skb);
+ printk("post 0x%x\n", (uint)skb);
X #endif
- skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- pB->context = (U32)skb;
- pB->scount = 1; /* segment count */
- pB->size = MAX_ETHER_SIZE;
- pB->addr = (U32)skb->data;
- p[0]++;
- pB++;
- }
+ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
+ pB->context = (U32)skb;
+ pB->scount = 1; /* segment count */
+ pB->size = MAX_ETHER_SIZE;
+ pB->addr = virt_to_bus((void *)skb->data);
+ p[0]++;
+ pB++;
+ }
X
- if ( (status = RCPostRecvBuffers(pDpa->id, (PRCTCB)p )) != RC_RTN_NO_ERROR)
- {
- printk("rc: Post buffer failed with error code 0x%x!\n", status);
- pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
- while(p[0])
- {
- skb = (struct sk_buff *)pB->context;
+ if ( (status = RCPostRecvBuffers(pDpa->id, (PRCTCB)p )) != RC_RTN_NO_ERROR)
+ {
+ printk("rc: Post buffer failed with error code 0x%x!\n", status);
+ pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
+ while(p[0])
+ {
+ skb = (struct sk_buff *)pB->context;
+#ifndef LINUX_2_1
+ skb->free = 1;
+#endif
X #ifdef RCDEBUG
- printk("rc: freeing 0x%x\n", (uint)skb);
+ printk("rc: freeing 0x%x\n", (uint)skb);
X #endif
- dev_kfree_skb(skb);
- p[0]--;
- pB++;
- }


+#ifdef LINUX_2_1
+ dev_kfree_skb (skb);
+#else

+ dev_kfree_skb(skb, FREE_READ);
+#endif
+ p[0]--;
+ pB++;
+ }
X #ifdef RCDEBUG
- printk("rc: freed all buffers, p[0] = %ld\n", p[0]);
+ printk("rc: freed all buffers, p[0] = %ld\n", p[0]);
X #endif
- }
- kfree(p);
- return(p[0]); /* return the number of posted buffers */
+ }
+ kfree(p);
+ return(p[0]); /* return the number of posted buffers */
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/net/znet.c linux/drivers/net/znet.c
--- v2.2.0-pre7/linux/drivers/net/znet.c Fri Jan 8 22:36:09 1999
+++ linux/drivers/net/znet.c Thu Jan 14 10:31:41 1999
@@ -207,11 +207,11 @@
X char *p;
X
X /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
- for(p = phys_to_virt(0xf0000); p < phys_to_virt(0x100000); p++)
+ for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++)
X if (*p == 'N' && strncmp(p, "NETIDBLK", 8) == 0)
X break;
X
- if (p >= pyhs_to_virt(0x100000)) {
+ if (p >= (char *)phys_to_virt(0x100000)) {
X if (znet_debug > 1)
X printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");
X return ENODEV;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.2.0-pre7/linux/drivers/pci/oldproc.c Thu Jan 7 15:11:37 1999
+++ linux/drivers/pci/oldproc.c Fri Jan 15 14:36:21 1999
@@ -162,8 +162,8 @@
X DEVICE( SI, SI_496, "85C496"),
X DEVICE( SI, SI_601, "85C601"),
X DEVICE( SI, SI_5107, "5107"),
- DEVICE( SI, SI_5511, "85C5511"),
- DEVICE( SI, SI_5513, "85C5513"),
+ DEVICE( SI, SI_5511, "85C5511"),
+ DEVICE( SI, SI_5513, "85C5513"),
X DEVICE( SI, SI_5571, "5571"),
X DEVICE( SI, SI_5591, "5591/5592 Host"),
X DEVICE( SI, SI_5597, "5597/5598 Host"),
@@ -253,6 +253,8 @@
X DEVICE( VISION, VISION_QD8580, "QD-8580"),
X DEVICE( BROOKTREE, BROOKTREE_848, "Bt848"),
X DEVICE( BROOKTREE, BROOKTREE_849A, "Bt849"),
+ DEVICE( BROOKTREE, BROOKTREE_878_1,"Bt878 2nd Contr. (?)"),
+ DEVICE( BROOKTREE, BROOKTREE_878, "Bt878"),
X DEVICE( BROOKTREE, BROOKTREE_8474, "Bt8474"),
X DEVICE( SIERRA, SIERRA_STB, "STB Horizon 64"),
X DEVICE( ACC, ACC_2056, "2056"),
@@ -371,9 +373,9 @@
X DEVICE( VORTEX, VORTEX_GDT6557RP2,"GDT 6557RP2"),
X DEVICE( VORTEX, VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2"),
X DEVICE( VORTEX, VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2"),
- DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)"),
- DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)"),
- DEVICE( FORE, FORE_PCA200PC, "PCA-200PC"),
+ DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)"),
+ DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)"),
+ DEVICE( FORE, FORE_PCA200PC, "PCA-200PC"),
X DEVICE( FORE, FORE_PCA200E, "PCA-200E"),
X DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI"),
X DEVICE( PHILIPS, PHILIPS_SAA7145,"SAA7145"),
@@ -435,6 +437,7 @@
X DEVICE( O2, O2_6832, "6832"),
X DEVICE( 3DFX, 3DFX_VOODOO, "Voodoo"),
X DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2"),
+ DEVICE( 3DFX, 3DFX_BANSHEE, "Banshee"),
X DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX"),
X DEVICE( STALLION, STALLION_ECHPCI832,"EasyConnection 8/32"),
X DEVICE( STALLION, STALLION_ECHPCI864,"EasyConnection 8/64"),
@@ -448,7 +451,7 @@
X DEVICE( SATSAGEM, SATSAGEM_TELSATTURBO,"Telsat Turbo DVB"),
X DEVICE( HUGHES, HUGHES_DIRECPC, "DirecPC"),
X DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI"),
- DEVICE( ALTEON, ALTEON_ACENIC,"AceNIC"),
+ DEVICE( ALTEON, ALTEON_ACENIC, "AceNIC"),
X DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST"),
X DEVICE( NVIDIA_SGS, NVIDIA_SGS_RIVA128, "Riva 128"),
X DEVICE( CBOARDS, CBOARDS_DAS1602_16,"DAS1602/16"),
@@ -468,7 +471,7 @@
X DEVICE( S3, S3_AURORA64VP, "Aurora64V+"),
X DEVICE( S3, S3_TRIO64UVP, "Trio64UV+"),
X DEVICE( S3, S3_ViRGE_VX, "ViRGE/VX"),
- DEVICE( S3, S3_868, "Vision 868"),
+ DEVICE( S3, S3_868, "Vision 868"),
X DEVICE( S3, S3_928, "Vision 928-P"),
X DEVICE( S3, S3_864_1, "Vision 864-P"),
X DEVICE( S3, S3_864_2, "Vision 864-P"),
@@ -584,7 +587,7 @@
X return 0;
X continue;
X }
-
+
X return & dev_info[ i ];
X }
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx
--- v2.2.0-pre7/linux/drivers/scsi/ChangeLog.ncr53c8xx Wed Dec 16 10:32:55 1998
+++ linux/drivers/scsi/ChangeLog.ncr53c8xx Sat Jan 16 16:57:16 1999
@@ -1,3 +1,16 @@
+Sat Jan 16 17:30 1998 Gerard Roudier (grou...@club-internet.fr)
+ * revision 3.1f
+ - Some PCI fix-ups not needed any more for PPC (from Cort).
+ - Cache line size set to 16 DWORDS for Sparc (from DSM).
+ - Waiting list look-up didn't work for the first command of the list.
+ - Remove 2 useless lines of code.
+
+Sun Dec 13 18:00 1998 Gerard Roudier (grou...@club-internet.fr)
+ * revision 3.1e
+ - Same work-around as for the 53c876 rev <= 0x15 for 53c896 rev 1:
+ Disable overlapped arbitration. This will not make difference
+ since the chip has on-chip RAM.
+
X Thu Nov 26 22:00 1998 Gerard Roudier (grou...@club-internet.fr)
X * revision 3.1d
X - The SISL RAID change requires now remap_pci_mem() stuff to be
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/NCR53c406a.c linux/drivers/scsi/NCR53c406a.c
--- v2.2.0-pre7/linux/drivers/scsi/NCR53c406a.c Fri Oct 23 22:01:21 1998
+++ linux/drivers/scsi/NCR53c406a.c Fri Jan 15 14:41:04 1999
@@ -656,10 +656,10 @@
X static void wait_intr() {
X int i = jiffies + WATCHDOG;
X
- while(i>jiffies && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */
+ while(time_after(i,jiffies) && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */
X barrier();
X
- if (i <= jiffies) { /* Timed out */
+ if (time_before_eq(i,jiffies)) { /* Timed out */
X rtrc(0);
X current_SC->result = DID_TIME_OUT << 16;
X current_SC->SCp.phase = idle;
@@ -983,9 +983,9 @@
X
X /* Wait for the interrupt to occur */
X i = jiffies + WATCHDOG;
- while(i > jiffies && !(inb(STAT_REG) & 0x80))
+ while(time_after(i, jiffies) && !(inb(STAT_REG) & 0x80))
X barrier();
- if (i <= jiffies) { /* Timed out, must be hardware trouble */
+ if (time_before_eq(i, jiffies)) { /* Timed out, must be hardware trouble */
X probe_irq_off(irqs);
X return -1;
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.2.0-pre7/linux/drivers/scsi/aha152x.c Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/aha152x.c Fri Jan 15 14:41:04 1999
@@ -575,7 +575,7 @@
X {
X unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
X
- while (jiffies < the_time)
+ while (time_before(jiffies, the_time))
X barrier();
X }
X
@@ -1038,7 +1038,7 @@
X SETBITS(DMACNTRL0, SWINT);
X
X the_time=jiffies+100;
- while(!HOSTDATA(shpnt)->swint && jiffies<the_time)
+ while(!HOSTDATA(shpnt)->swint && time_before(jiffies, the_time))
X barrier();
X
X free_irq(shpnt->irq,shpnt);
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.2.0-pre7/linux/drivers/scsi/aic7xxx.c Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/aic7xxx.c Sun Jan 17 18:28:06 1999
@@ -513,8 +513,8 @@
X * Make a define that will tell the driver not to use tagged queueing
X * by default.
X */
-#define DEFAULT_TAG_COMMANDS {0, 0, 0, 0, 0, 0, 0, 0,\
- 0, 0, 0, 0, 0, 0, 0, 0}
+#define DEFAULT_TAG_COMMANDS {255, 255, 255, 255, 255, 255, 255, 255,\
+ 255, 255, 255, 255, 255, 255, 255, 255}
X
X /*
X * Modify this as you see fit for your system. By setting tag_commands
@@ -9017,8 +9017,8 @@
X {
X printk("aic7xxx: <%s> at PCI %d/%d\n",
X board_names[aic_pdevs[i].board_name_index],
- PCI_SLOT(temp_p->pdev->devfn),
- PCI_FUNC(temp_p->pdev->devfn));
+ PCI_SLOT(temp_p->pci_device_fn),
+ PCI_FUNC(temp_p->pci_device_fn));
X printk("aic7xxx: Controller disabled by BIOS, ignoring.\n");
X kfree(temp_p);
X temp_p = NULL;
@@ -9050,8 +9050,8 @@
X */
X printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n",
X board_names[aic_pdevs[i].board_name_index],
- PCI_SLOT(temp_p->pdev->devfn),
- PCI_FUNC(temp_p->pdev->devfn));
+ PCI_SLOT(temp_p->pci_device_fn),
+ PCI_FUNC(temp_p->pci_device_fn));
X printk(KERN_INFO "aic7xxx: MMAPed I/O failed, reverting to "
X "Programmed I/O.\n");
X #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.2.0-pre7/linux/drivers/scsi/hosts.c Tue Dec 22 14:16:56 1998
+++ linux/drivers/scsi/hosts.c Sun Jan 17 18:32:26 1999
@@ -452,6 +452,9 @@
X #ifdef CONFIG_SCSI_AIC7XXX
X AIC7XXX,
X #endif
+#ifdef CONFIG_FD_MCS
+ FD_MCS,
+#endif
X #ifdef CONFIG_SCSI_FUTURE_DOMAIN
X FDOMAIN_16X0,
X #endif
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/i91uscsi.c linux/drivers/scsi/i91uscsi.c
--- v2.2.0-pre7/linux/drivers/scsi/i91uscsi.c Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/i91uscsi.c Thu Jan 14 10:31:41 1999
@@ -510,10 +510,10 @@
X if (i91u_adpt[i].ADPT_BIOS < wBIOS)
X continue;
X if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
- if (i91u_adpt[i].ADPT_BASE == wBASE)
+ if (i91u_adpt[i].ADPT_BASE == wBASE) {
X if (i91u_adpt[i].ADPT_Bus != 0xFF)
X return (FAILURE);
- else if (i91u_adpt[i].ADPT_BASE < wBASE)
+ } else if (i91u_adpt[i].ADPT_BASE < wBASE)
X continue;
X }
X for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- v2.2.0-pre7/linux/drivers/scsi/ide-scsi.c Tue Jul 28 14:21:08 1998
+++ linux/drivers/scsi/ide-scsi.c Fri Jan 15 14:41:04 1999
@@ -23,6 +23,8 @@
X * Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer
X * for access through /dev/sg.
X * Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
+ * Ver 0.7 Dev 04 98 Ignore commands where lun != 0 to avoid multiple
+ * detection of devices with CONFIG_SCSI_MULTI_LUN
X */
X
X #define IDESCSI_VERSION "0.6"
@@ -726,6 +728,9 @@
X
X if (!drive) {
X printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->target);
+ goto abort;
+ }
+ if (cmd->lun != 0) { /* Only respond to LUN 0. Drop others */
X goto abort;
X }
X scsi = drive->driver_data;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/mac_NCR5380.c linux/drivers/scsi/mac_NCR5380.c
--- v2.2.0-pre7/linux/drivers/scsi/mac_NCR5380.c Mon Aug 3 12:45:46 1998
+++ linux/drivers/scsi/mac_NCR5380.c Fri Jan 15 14:41:04 1999
@@ -1458,9 +1458,9 @@
X unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
X
X while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
- && jiffies < timeout && !hostdata->connected)
+ && time_before(jiffies, timeout) && !hostdata->connected)
X ;
- if (jiffies >= timeout)
+ if (time_after_eq(jiffies, timeout))
X {
X printk("scsi : arbitration timeout at %d\n", __LINE__);
X NCR5380_write(MODE_REG, MR_BASE);
@@ -1615,7 +1615,7 @@
X * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
X */
X
- while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) &
+ while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) &
X (SR_BSY | SR_IO)));
X
X if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) ==
@@ -1628,7 +1628,7 @@
X return -1;
X }
X #else
- while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
+ while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));


X #endif
X
X /*

diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/mac_scsi.c linux/drivers/scsi/mac_scsi.c
--- v2.2.0-pre7/linux/drivers/scsi/mac_scsi.c Mon Aug 3 12:45:46 1998
+++ linux/drivers/scsi/mac_scsi.c Fri Jan 15 14:41:04 1999
@@ -662,7 +662,7 @@
X NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
X NCR5380_read( RESET_PARITY_INTERRUPT_REG );
X
- for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
+ for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
X barrier();
X
X /* switch on SCSI IRQ again */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.2.0-pre7/linux/drivers/scsi/ncr53c8xx.c Wed Dec 16 10:32:55 1998
+++ linux/drivers/scsi/ncr53c8xx.c Sun Jan 17 18:28:06 1999
@@ -73,7 +73,7 @@
X */
X
X /*
-** November 26 1998, version 3.1d
+** January 16 1998, version 3.1f
X **
X ** Supported SCSI-II features:
X ** Synchronous negotiation
@@ -1010,7 +1010,7 @@
X #endif
X
X /*
-** If the CPU and the NCR use same endian-ness adressing,
+** If the CPU and the NCR use same endian-ness addressing,
X ** no byte reordering is needed for script patching.
X ** Macro cpu_to_scr() is to be used for script patching.
X ** Macro scr_to_cpu() is to be used for getting a DWORD
@@ -1049,7 +1049,7 @@
X */
X
X /*
-** If the CPU and the NCR use same endian-ness adressing,
+** If the CPU and the NCR use same endian-ness addressing,
X ** no byte reordering is needed for accessing chip io
X ** registers. Functions suffixed by '_raw' are assumed
X ** to access the chip over the PCI without doing byte
@@ -6182,10 +6182,14 @@
X /*
X ** DEL 441 - 53C876 Rev 5 - Part Number 609-0392787/2788 - ITEM 2.
X ** Disable overlapped arbitration.
+ ** The 896 Rev 1 is also affected by this errata.
X */
X if (np->device_id == PCI_DEVICE_ID_NCR_53C875 &&
X np->revision_id >= 0x10 && np->revision_id <= 0x15)
X OUTB (nc_ctest0, (1<<5));
+ else if (np->device_id == PCI_DEVICE_ID_NCR_53C896 &&
+ np->revision_id <= 0x1)
+ OUTB (nc_ccntl0, DPR);
X
X /*
X ** Fill in target structure.
@@ -6811,7 +6815,7 @@
X ** scntl3: (see the manual)
X **
X ** current script command:
-** dsp: script adress (relative to start of script).
+** dsp: script address (relative to start of script).
X ** dbc: first word of script command.
X **
X ** First 16 register of the chip:
@@ -9637,7 +9641,7 @@
X (void) pcibios_read_config_dword(bus, device_fn,
X PCI_BASE_ADDRESS_2, &base_2);
X
- /* Handle 64bit base adresses for 53C896. */
+ /* Handle 64bit base addresses for 53C896. */
X if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
X (void) pcibios_read_config_dword(bus, device_fn,
X PCI_BASE_ADDRESS_3, &base_2);
@@ -9738,7 +9742,9 @@
X printk("succeeded.\n");
X }
X }
-
+
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,140)
X if ( is_prep ) {
X if (io_port >= 0x10000000) {
X printk("ncr53c8xx: reallocating io_port (Wacky IBM)");
@@ -9756,6 +9762,7 @@
X pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, base_2);
X }
X }
+#endif
X #endif /* __powerpc__ */
X
X #ifdef __sparc__
@@ -9786,7 +9793,8 @@
X }
X
X if ((chip->features & FE_CLSE) && !cache_line_size) {
- cache_line_size = CACHE_LINE_SIZE;
+ /* PCI_CACHE_LINE_SIZE value is in 32-bit words. */
+ cache_line_size = 64 / sizeof(u_int32);
X if (initverbose >= 2)
X printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size);
X pcibios_write_config_byte(bus, device_fn,
@@ -9796,7 +9804,7 @@
X }
X
X if (!latency_timer) {
- latency_timer = 248;
+ latency_timer = 128;
X if (initverbose >= 2)
X printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer);
X pcibios_write_config_byte(bus, device_fn,
@@ -10148,8 +10156,6 @@
X
X cmd->scsi_done = done;
X cmd->host_scribble = NULL;
- cmd->SCp.ptr = NULL;
- cmd->SCp.buffer = NULL;
X
X NCR_LOCK_NCB(np, flags);
X
@@ -10384,13 +10390,12 @@
X
X static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd)
X {
- Scsi_Cmnd *wcmd;
+ Scsi_Cmnd **pcmd = &np->waiting_list;
X
- if (!(wcmd = np->waiting_list)) return 0;
- while (wcmd->next_wcmd) {
- if (cmd == (Scsi_Cmnd *) wcmd->next_wcmd) {
+ while (*pcmd) {
+ if (cmd == *pcmd) {
X if (to_remove) {
- wcmd->next_wcmd = cmd->next_wcmd;
+ *pcmd = (Scsi_Cmnd *) cmd->next_wcmd;
X cmd->next_wcmd = 0;
X }
X #ifdef DEBUG_WAITING_LIST
@@ -10398,6 +10403,7 @@
X #endif
X return cmd;
X }
+ pcmd = (Scsi_Cmnd **) &(*pcmd)->next_wcmd;
X }
X return 0;
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.2.0-pre7/linux/drivers/scsi/ncr53c8xx.h Wed Dec 16 10:32:55 1998
+++ linux/drivers/scsi/ncr53c8xx.h Mon Jan 18 17:34:32 1999
@@ -45,7 +45,7 @@
X /*
X ** Name and revision of the driver
X */
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1d"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1f"
X
X /*
X ** Check supported Linux versions


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 10'
echo 'File patch-2.2.0-pre8 is continued in part 11'
echo 11 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part11

#!/bin/sh
# this is part 11 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 11; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

@@ -346,7 +346,7 @@
X #endif
X
X #ifdef SCSI_NCR_BIG_ENDIAN
-#error "The NCR in BIG ENDIAN adressing mode is not (yet) supported"
+#error "The NCR in BIG ENDIAN addressing mode is not (yet) supported"


X #endif
X
X /*

@@ -768,7 +768,20 @@
X
X /*53*/ u_char nc_53_;
X /*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */
-/*56*/ u_short nc_56_;
+/*56*/ u_char nc_ccntl0; /* Chip Control 0 (896) */
+ #define ENPMJ 0x80 /* Enable Phase Mismatch Jump */
+ #define PMJCTL 0x40 /* Phase Mismatch Jump Control */
+ #define ENNDJ 0x20 /* Enable Non Data PM Jump */
+ #define DISFC 0x10 /* Disable Auto FIFO Clear */
+ #define DILS 0x02 /* Disable Internal Load/Store */
+ #define DPR 0x01 /* Disable Pipe Req */
+
+/*57*/ u_char nc_ccntl1; /* Chip Control 1 (896) */
+ #define ZMOD 0x80 /* High Impedance Mode */
+ #define DDAC 0x08 /* Disable Dual Address Cycle */
+ #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */
+ #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */
+ #define EXDBMV 0x01 /* Enable 64-bit Direct BMOV */
X /*58*/ u_short nc_sbdl; /* Lowlevel: data from scsi data */
X /*5a*/ u_short nc_5a_;
X /*5c*/ u_char nc_scr0; /* Working register B */
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.2.0-pre7/linux/drivers/scsi/scsi.c Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/scsi.c Sun Jan 17 18:29:54 1999
@@ -1749,7 +1749,7 @@
X host_active = NULL;
X
X /* For block devices "wake_up" is done in end_scsi_request */
- if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
+ if (!SCSI_BLK_MAJOR(MAJOR(SCpnt->request.rq_dev))) {
X struct Scsi_Host * next;
X
X for (next = host->block; next != host; next = next->block)
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c
--- v2.2.0-pre7/linux/drivers/scsi/scsi_obsolete.c Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/scsi_obsolete.c Sun Jan 17 18:29:54 1999
@@ -671,7 +671,7 @@
X host_active = NULL;
X
X /* For block devices "wake_up" is done in end_scsi_request */
- if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
+ if (!SCSI_BLK_MAJOR(MAJOR(SCpnt->request.rq_dev))) {
X struct Scsi_Host * next;
X
X for (next = host->block; next != host; next = next->block)
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.2.0-pre7/linux/drivers/scsi/sd.c Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/sd.c Sun Jan 17 18:29:54 1999
@@ -1482,12 +1482,11 @@
X if (!rscsi_disks)
X sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
X
- /* 128 disks is our current limit (8 majors, 16 disks per major) */
- if(sd_template.dev_max > 128)
- sd_template.dev_max = 128;
+ if(sd_template.dev_max > N_SD_MAJORS * SCSI_DISKS_PER_MAJOR )
+ sd_template.dev_max = N_SD_MAJORS * SCSI_DISKS_PER_MAJOR;
X
X if(!sd_registered) {
- for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) {
X if (register_blkdev(SD_MAJOR(i),"sd",&sd_fops)) {
X printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i));
X return 1;
@@ -1540,8 +1539,9 @@
X sd_gendisks[i].real_devices =
X (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
X }
+
X LAST_SD_GENDISK.max_nr =
- sd_template.dev_max % SCSI_DISKS_PER_MAJOR;
+ (sd_template.dev_max -1 ) % SCSI_DISKS_PER_MAJOR + 1;
X LAST_SD_GENDISK.next = NULL;
X return 0;
X }
@@ -1559,7 +1559,7 @@
X struct gendisk *gendisk;
X int i;
X
- for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) {
X /* FIXME: After 2.2 we should implement multiple sd queues */
X blk_dev[SD_MAJOR(i)].request_fn = DEVICE_REQUEST;
X if (i) blk_dev[SD_MAJOR(i)].queue = sd_get_queue;
@@ -1765,7 +1765,7 @@
X
X scsi_unregister_module(MODULE_SCSI_DEV, &sd_template);
X
- for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++)
+ for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++)
X unregister_blkdev(SD_MAJOR(i),"sd");
X
X sd_registered--;
@@ -1794,11 +1794,11 @@
X
X if (removed != N_USED_SD_MAJORS)
X printk("%s %d sd_gendisks in disk chain",
- removed > N_USED_SD_MAJORS ? "total" : "just", removed);
+ removed > N_USED_SD_MAJORS ? "total" : "just", removed);
X
X }
X
- for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) {
X blk_dev[SD_MAJOR(i)].request_fn = NULL;
X blk_size[SD_MAJOR(i)] = NULL;
X hardsect_size[SD_MAJOR(i)] = NULL;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.2.0-pre7/linux/drivers/scsi/sr.c Thu May 14 19:47:41 1998
+++ linux/drivers/scsi/sr.c Fri Jan 15 14:41:04 1999
@@ -63,7 +63,6 @@
X static int * sr_sizes = NULL;
X
X static int * sr_blocksizes = NULL;
-static int * sr_hardsizes = NULL; /* Hardware sector size */
X
X static int sr_open(struct cdrom_device_info*, int);
X void get_sectorsize(int);
@@ -154,8 +153,7 @@
X */
X scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
X
- scsi_CDs[MINOR(cdi->dev)].sector_size =
- sr_hardsizes[MINOR(cdi->dev)] = 2048;
+ scsi_CDs[MINOR(cdi->dev)].sector_size = 2048;
X }
X return retval;
X }
@@ -955,7 +953,6 @@
X * Add this so that we have the ability to correctly gauge
X * what the device is capable of.
X */
- sr_hardsizes[i] = scsi_CDs[i].sector_size;
X scsi_CDs[i].needs_sector_size = 0;
X sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
X };
@@ -1040,16 +1037,12 @@
X
X sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max *
X sizeof(int), GFP_ATOMIC);
- sr_hardsizes = (int *) scsi_init_malloc(sr_template.dev_max *
- sizeof(int), GFP_ATOMIC);
X
X /*
X * These are good guesses for the time being.
X */
X for(i=0;i<sr_template.dev_max;i++) sr_blocksizes[i] = 2048;
- for(i=0;i<sr_template.dev_max;i++) sr_hardsizes[i] = 2048;
X blksize_size[MAJOR_NR] = sr_blocksizes;
- hardsect_size[MAJOR_NR] = sr_hardsizes;


X return 0;
X }
X

@@ -1163,9 +1156,6 @@
X
X scsi_init_free((char *) sr_blocksizes, sr_template.dev_max * sizeof(int));
X sr_blocksizes = NULL;
-
- scsi_init_free((char *) sr_hardsizes, sr_template.dev_max * sizeof(int));
- sr_hardsizes = NULL;
X }
X
X blksize_size[MAJOR_NR] = NULL;
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.2.0-pre7/linux/drivers/sound/Config.in Thu Jan 7 15:11:37 1999
+++ linux/drivers/sound/Config.in Thu Jan 14 22:59:47 1999
@@ -9,20 +9,18 @@
X
X # Prompt user for primary drivers.
X
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
- if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
- bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
- fi
- dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
- if [ "$CONFIG_SOUND_ES1371" = "y" ]; then
- bool 'Joystick support at boot time' CONFIG_SOUND_ES1371_JOYPORT_BOOT
- if [ "$CONFIG_SOUND_ES1371_JOYPORT_BOOT" = "y" ]; then
- hex 'Gameport I/O 200,208,210,218' CONFIG_SOUND_ES1371_GAMEPORT 200
- fi
- fi
- dep_tristate 'S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
+dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
+if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
+ bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
+fi
+dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
+if [ "$CONFIG_SOUND_ES1371" = "y" ]; then
+ bool 'Joystick support at boot time' CONFIG_SOUND_ES1371_JOYPORT_BOOT
+ if [ "$CONFIG_SOUND_ES1371_JOYPORT_BOOT" = "y" ]; then
+ hex 'Gameport I/O 200,208,210,218' CONFIG_SOUND_ES1371_GAMEPORT 200
+ fi
X fi
+dep_tristate 'S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
X
X dep_tristate 'Support for Turtle Beach MultiSound Classic, Tahiti, Monterey' CONFIG_SOUND_MSNDCLAS $CONFIG_SOUND
X if [ "$CONFIG_SOUND_MSNDCLAS" = "y" -o "$CONFIG_SOUND_MSNDCLAS" = "m" ]; then
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.2.0-pre7/linux/drivers/sound/Makefile Thu Jan 7 15:11:37 1999
+++ linux/drivers/sound/Makefile Thu Jan 14 22:59:47 1999
@@ -95,7 +95,8 @@
X
X gus-objs := gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
X pas2-objs := pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
-sb-objs := sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o
+sb-objs := sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o \
+ sb_ess.o
X softoss2-objs := softoss.o softoss_rs.o
X vidc_mod-objs := vidc.o vidc_audio.o vidc_fill.o vidc_mixer.o vidc_synth.o
X wavefront-objs := wavfront.o wf_midi.o yss225.o
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/README.FIRST linux/drivers/sound/README.FIRST
--- v2.2.0-pre7/linux/drivers/sound/README.FIRST Sat Sep 5 16:46:41 1998
+++ linux/drivers/sound/README.FIRST Sun Jan 17 18:23:01 1999
@@ -4,4 +4,3 @@
X forums for bug reporting.
X
X Alan Cox
-
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/README.blurb linux/drivers/sound/README.blurb
--- v2.2.0-pre7/linux/drivers/sound/README.blurb Tue Dec 23 13:52:02 1997
+++ linux/drivers/sound/README.blurb Wed Dec 31 16:00:00 1969
@@ -1,10 +0,0 @@
-*********************************************************
-* Readme.cards (this directory) contains some card *
-* specific instructions. *
-* See http://www.4front-tech.com/ossfree for most up *
-* to date info. *
-* (European mirror http://personal.eunet.fi/pp/voxware) *
-* *
-* DON'T USE PROGRAMS FROM snd-util PACKAGE EARLIER THAN *
-* snd-util-3.5 WITH THIS SOUND DRIVER VERSION. *
-*********************************************************
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/README.wavefront linux/drivers/sound/README.wavefront
--- v2.2.0-pre7/linux/drivers/sound/README.wavefront Sun Jul 26 11:57:16 1998
+++ linux/drivers/sound/README.wavefront Wed Dec 31 16:00:00 1969
@@ -1,375 +0,0 @@
- An OSS/Free Driver for WaveFront Sound Cards
- (Turtle Beach Maui, Tropez, Tropez Plus)
-
- Paul Barton-Davis, July 1998
-
- VERSION 0.2.2
-
-Driver Status
--------------
-
-Requires: Kernel 2.1.106 or later
-
-As of 7/13/1998, this driver is currently in *BETA* state. This means
-that it compiles and runs, and that I use it on my system (Linux
-2.1.106) with some reasonably demanding applications and uses. I
-believe the code is approaching an initial "finished" state that
-provides bug-free support for the Tropez Plus.
-
-Please note that to date, the driver has ONLY been tested on a Tropez
-Plus. I would very much like to hear (and help out) people with Tropez
-and Maui cards, since I think the driver can support those cards as
-well.
-
-Finally, the driver has not been tested as a static (non-modular) part
-of the kernel. Alan Cox's good work in modularizing OSS/Free for Linux
-makes this rather unnecessary.
-
-Some Questions
---------------
-
-**********************************************************************
-0) What does this driver do that the maui driver did not ?
-**********************************************************************
-
-* can fully initialize a WaveFront card from cold boot - no DOS
- utilities needed
-* working patch/sample/program loading and unloading (the maui
- driver didn't document how to make this work, and assumed
- user-level preparation of the patch data for writing
- to the board. ick.)
-* full user-level access to all WaveFront commands
-* for the Tropez Plus, (primitive) control of the YSS225 FX processor
-* Virtual MIDI mode supported - 2 MIDI devices accessible via the
- WaveFront's MPU401/UART emulation. One
- accesses the WaveFront synth, the other accesses the
- external MIDI connector. Full MIDI read/write semantics
- for both devices.
-* OSS-compliant /dev/sequencer interface for the WaveFront synth,
- including native and GUS-format patch downloading.
-* semi-intelligent patch management (prototypical at this point)
-
-
-**********************************************************************
-1) What to do about MIDI interfaces ?
-**********************************************************************
-
-The Tropez Plus (and perhaps other WF cards) can in theory support up
-to 2 physical MIDI interfaces. One of these is connected to the
-ICS2115 chip (the WaveFront synth itself) and is controlled by
-MPU/UART-401 emulation code running as part of the WaveFront OS. The
-other is controlled by the CS4232 chip present on the board. However,
-physical access to the CS4232 connector is difficult, and it is
-unlikely (though not impossible) that you will want to use it.
-
-An older version of this driver introduced an additional kernel config
-variable which controlled whether or not the CS4232 MIDI interface was
-configured. Because of Alan Cox's work on modularizing the sound
-drivers, and now backporting them to 2.0.34 kernels, there seems to be
-little reason to support "static" configuration variables, and so this
-has been abandoned in favor of *only* module parameters. Specifying
-"mpuio" and "mpuirq" for the cs4232 parameter will result in the
-CS4232 MIDI interface being configured; leaving them unspecified will
-leave it unconfigured (and thus unusable).
-
-BTW, I have heard from one Tropez+ user that the CS4232 interface is
-more reliable than the ICS2115 one. I have had no problems with the
-latter, and I don't have the right cable to test the former one
-out. Reports welcome.
-
-**********************************************************************
-2) Why does line XXX of the code look like this .... ?
-**********************************************************************
-
-Either because its not finished yet, or because you're a better coder
-than I am, or because you don't understand some aspect of how the card
-or the code works.
-
-I absolutely welcome comments, criticisms and suggestions about the
-design and implementation of the driver.
-
-**********************************************************************
-3) What files are included ?
-**********************************************************************
-
- drivers/sound/README.wavefront -- this file
- drivers/sound/wavefront.patch -- patches for the 2.1.106 sound drivers
- needed to make the rest of this work
- drivers/sound/wavfront.c -- the driver
- drivers/sound/ys225.h -- data declarations for FX config
- drivers/sound/ys225.c -- data definitions for FX config
- drivers/sound/wf_midi.c -- the "uart401" driver
- to support virtual MIDI mode.
- include/wavefront.h -- the header file
- Documentation/sound/Tropez+ -- short docs on configuration
-
-**********************************************************************
-4) How do I compile/install/use it ?
-**********************************************************************
-
-PART ONE: install the source code into your sound driver directory
-
- cd <top-of-your-2.1.106-code-base-e.g.-/usr/src/linux>
- tar -zxvf <where-you-put/wavefront.tar.gz>
-
-PART TWO: apply the patches
-
- cd drivers/sound
- patch < wavefront.patch
-
-PART THREE: configure your kernel
-
- cd <top of your kernel tree>
- make xconfig (or whichever config option you use)
-
- - choose YES for Sound Support
- - choose MODULE (M) for OSS Sound Modules
- - choose MODULE(M) to YM3812/OPL3 support
- - choose MODULE(M) for WaveFront support
- - choose MODULE(M) for CS4232 support
-
- - choose "N" for everything else (unless you have other
- sound cards you want support for)
-
-
- make dep
- make boot
- .
- .
- .
- <whatever you normally do for a kernel install>
- make modules
- .
- .
- .
- make modules_install
-
-Here's my autoconf.h SOUND section:
-
-/*
- * Sound
- */
-#define CONFIG_SOUND 1
-#undef CONFIG_SOUND_OSS
-#define CONFIG_SOUND_OSS_MODULE 1
-#undef CONFIG_SOUND_PAS
-#undef CONFIG_SOUND_SB
-#undef CONFIG_SOUND_ADLIB
-#undef CONFIG_SOUND_GUS
-#undef CONFIG_SOUND_MPU401
-#undef CONFIG_SOUND_PSS
-#undef CONFIG_SOUND_MSS
-#undef CONFIG_SOUND_SSCAPE
-#undef CONFIG_SOUND_TRIX
-#undef CONFIG_SOUND_MAD16
-#undef CONFIG_SOUND_WAVEFRONT
-#define CONFIG_SOUND_WAVEFRONT_MODULE 1
-#undef CONFIG_SOUND_CS4232
-#define CONFIG_SOUND_CS4232_MODULE 1
-#undef CONFIG_SOUND_MAUI
-#undef CONFIG_SOUND_SGALAXY
-#undef CONFIG_SOUND_OPL3SA1
-#undef CONFIG_SOUND_SOFTOSS
-#undef CONFIG_SOUND_YM3812
-#define CONFIG_SOUND_YM3812_MODULE 1
-#undef CONFIG_SOUND_VMIDI
-#undef CONFIG_SOUND_UART6850
-/*
- * Additional low level sound drivers
- */
-#undef CONFIG_LOWLEVEL_SOUND
-
-************************************************************
-6) How do I configure my card ?
-************************************************************
-
-You need to edit /etc/conf.modules. Here's mine (edited to show the
-relevant details):
-
- # Sound system
- alias char-major-14 wavefront
- alias synth0 wavefront
- alias mixer0 cs4232
- alias audio0 cs4232
- pre-install wavefront modprobe "-k" "cs4232"
- post-install wavefront modprobe "-k" "opl3"
- options wavefront io=0x200 irq=9
- options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0
- options opl3 io=0x388
-
-Things to note:
-
- the wavefront options "io" and "irq" ***MUST*** match the "synthio"
- and "synthirq" cs4232 options.
-
- you can do without the adlib_card module if you don't
- want to use the OPL/[34] synth on the sound card
-
- the adlib_card io parameter is conventionally not adjustable.
- In theory, any not-in-use IO port address would work, but
- just use 0x388 and stick with the crowd.
-
-**********************************************************************
-7) What about firmware ?
-**********************************************************************
-
-Turtle Beach have not given me permission to distribute their firmware
-for the ICS2115. However, if you have a WaveFront card, then you
-almost certainly have the firmware, and if not, its freely available
-on their website, at:
-
- http://www.tbeach.com/tbs/downloads/scardsdown.htm#tropezplus
-
-The file is called WFOS2001.MOT (for the Tropez+).
-
-This driver, however, doesn't use the pure firmware as distributed,
-but instead relies on a somewhat processed form of it. You can
-generate this very easily. Following an idea from Andrew Veliath's
-Pinnacle driver, the following flex program will generate the
-processed version:
-
----- cut here -------------------------
-%option main
-%%
-^S[28].*\r$ printf ("%c%.*s", yyleng-1,yyleng-1,yytext);
-<<EOF>> { fputc ('\0', stdout); return; }
-\n {}
-. {}
----- cut here -------------------------
-
-To use it, put the above in file (say, ws.l) compile it like this:
-
- shell> flex -ows.c ws.l
- shell> cc -o ws ws.c
-
-and then use it like this:
-
- ws < my-copy-of-the-oswf.mot-file > /etc/sound/wavefront.os
-
-If you put it somewhere else, you'll always have to use the wf_ospath
-module parameter (see below) or alter the source code.
-
-**********************************************************************
-7) How do I get it working ?
-**********************************************************************
-
-Optionally, you can reboot with the "new" kernel (even though the only
-changes have really been made to a module).
-
-Then, as root do:
-
- modprobe wavefront
-
-You should get something like this in /var/log/messages:
-
- WaveFront: firmware 1.20 already loaded.
-
-or
-
- WaveFront: no response to firmware probe, assume raw.
-
-then:
-
- WaveFront: waiting for memory configuration ...
- WaveFront: hardware version 1.64
- WaveFront: available DRAM 8191k
- WaveFront: 332 samples used (266 real, 13 aliases, 53 multi), 180 empty
- WaveFront: 128 programs slots in use
- WaveFront: 256 patch slots filled, 142 in use
-
-The whole process takes about 16 seconds, the longest waits being
-after reporting the hardware version (during the firmware download),
-and after reporting program status (during patch status inquiry). Its
-shorter (about 10 secs) if the firmware is already loaded (i.e. only
-warm reboots since the last firmware load).
-
-The "available DRAM" line will vary depending on how much added RAM
-your card has. Mine has 8MB.
-
-Next, check /dev/sndstat, which on my machine says:
----------------------------------------------------------------------
-OSS/Free:3.8s2++-971130
-Load type: Driver loaded as a module
-Kernel: Linux bd 2.1.106 #12 SMP Fri Jul 3 00:37:34 EDT 1998 i486
-Config options: 0
-
-Installed drivers:
-
-Card config:
-
-Audio devices:
-0: Crystal audio controller (CS4232) (DUPLEX)
-
-Synth devices:
-0: Turtle Beach WaveFront
-1: Yamaha OPL-3
-
-Midi devices:
-0: WaveFront Internal MIDI
-1: WaveFront External MIDI
-
-Timers:
-0: System clock
-1: Crystal audio controller (CS4232)
-
-Mixers:
-0: Crystal audio controller (CS4232)
------------------------------------------------------------
-
-To check basically functionality, use play(1) or splay(1) to send a
-.WAV or other audio file through the audio portion. Then use playmidi
-to play a General MIDI file. Try the "-D 0" to hear the
-difference between sending MIDI to the WaveFront and using the OPL/3,
-which is the default (I think ...). If you have an external synth(s)
-hooked to the sound card, you can use "-e" to route to the
-external synth(s) (in theory, -D 1 should work as well, but I think
-there is a bug in playmidi which prevents this from doing what it
-should).
-
-**********************************************************************
-8) What are the module parameters ?
-**********************************************************************
-
-Its best to read wavefront.c for this, but here is a summary:
-
-integers:
- wf_raw - if set, ignore apparent presence of firmware
- loaded onto the ICS2115, reset the whole
- board, and initialize it from scratch. (default = 0)
-
- fx_raw - if set, always initialize the YSS225 processor
- on the Tropez plus. (default = 1)
-
- < The next 4 are basically for kernel hackers to allow
- tweaking the driver for testing purposes. >
-
- wf_short_wait_count - loop counter used when waiting for
- status conditions on the board. This
- is CPU-specific. After this many
- loops, the driver will sleep.
- The default is 5000. I have a 66Mhz 486.
-
- wf_sleep_interval - the driver sleeps for
- HZ/wf_sleep_interval seconds per sleep.
- The default is 50.
-
- wf_sleep_tries - the number of times the driver will sleep
- when waiting for a status condition on the
- board. The default is 100 (2 secs, if
- wf_sleep_interval is 50).
-
- wf_debug_default - debugging flags. See sound/wavefront.h
- for WF_DEBUG_* values. Default is zero.
- Setting this allows you to debug the
- driver during module installation.
-strings:
- wf_ospath - path to get to the pre-processed OS firmware.
- (default: /etc/sound/wavefront.os)
-
-**********************************************************************
-9) Who should I contact if I have problems?
-**********************************************************************
-
-Just me: Paul Barton-Davis <p...@op.net>
-
-
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/Readme linux/drivers/sound/Readme
--- v2.2.0-pre7/linux/drivers/sound/Readme Fri Oct 23 22:01:21 1998
+++ linux/drivers/sound/Readme Wed Dec 31 16:00:00 1969
@@ -1,186 +0,0 @@
-OSS/Free version 3.8 release notes
-----------------------------------
-
-Most up to date information about this driver is available from
-http://www.opensound.com/ossfree.
-
-
-
-Please read the SOUND-HOWTO (available from sunsite.unc.edu and other Linux FTP
-sites). It gives instructions about using sound with Linux. It's bit out of
-date but still very useful. Information about bug fixes and such things
-is available from the web page (see above).
-
-Please check http://www.opensound.com/pguide for more info about programming
-with OSS API.
-
- ====================================================
-- THIS VERSION ____REQUIRES____ Linux 2.1.57 OR LATER.
- ====================================================
-
-Packages "snd-util-3.8.tar.gz" and "snd-data-0.1.tar.Z"
-contain useful utilities to be used with this driver.
-See http://www.opensound.com/ossfree/getting.html for
-download instructions.
-
-If you are looking for the installation instructions, please
-look at Readme.linux.
-
-Supported sound cards
----------------------
-
-See Readme.cards.
-
-Please check http://www.opensound.com/ossfree if you don't find
-your sound card there.
-
-Contributors
-------------
-
-This driver contains code by several contributors. In addition several other
-persons have given useful suggestions. The following is a list of major
-contributors. (I could have forgotten some names.)
-
- Craig Metz 1/2 of the PAS16 Mixer and PCM support
- Rob Hooft Volume computation algorithm for the FM synth.
- Mika Liljeberg uLaw encoding and decoding routines
- Jeff Tranter Linux SOUND HOWTO document
- Greg Lee Volume computation algorithm for the GUS and
- lot's of valuable suggestions.
- Andy Warner ISC port
- Jim Lowe,
- Amancio Hasty Jr FreeBSD/NetBSD port
- Anders Baekgaard Bug hunting and valuable suggestions.
- Joerg Schubert SB16 DSP support (initial version).
- Andrew Robinson Improvements to the GUS driver
- Megens SA MIDI recording for SB and SB Pro (initial version).
- Mikael Nordqvist Linear volume support for GUS and
- nonblocking /dev/sequencer.
- Ian Hartas SVR4.2 port
- Markus Aroharju and
- Risto Kankkunen Major contributions to the mixer support
- of GUS v3.7.
- Hunyue Yau Mixer support for SG NX Pro.
- Marc Hoffman PSS support (initial version).
- Rainer Vranken Initialization for Jazz16 (initial version).
- Peter Trattler Initial version of loadable module support for Linux.
- JRA Gibson 16 bit mode for Jazz16 (initial version)
- Davor Jadrijevic MAD16 support (initial version)
- Gregor Hoffleit Mozart support (initial version)
- Riccardo Facchetti Audio Excel DSP 16 (aedsp16) support
- James Hightower Spotting a tiny but important bug in CS423x support.
- Denis Sablic OPTi 82C924 spesific enhancements (non PnP mode)
- Tim MacKenzie Full duplex support for OPTi 82C930.
-
- Please look at lowlevel/README for more contributors.
-
-There are probably many other names missing. If you have sent me some
-patches and your name is not in the above list, please inform me.
-
-Sending your contributions or patches
--------------------------------------
-
-First of all it's highly recommended to contact me before sending anything
-or before even starting to do any work. Tell me what you suggest to be
-changed or what you have planned to do. Also ensure you are using the
-very latest (development) version of OSS/Free since the change may already be
-implemented there. In general it's major waste of time to try to improve
-several months old version. Information about the latest version can be found
-from http://www.opensound.com/ossfree. In general there is no point in
-sending me patches relative to production kernels.
-
-Sponsors etc.
--------------
-
-The following companies have greatly helped development of this driver
-in form of a free copy of their product:
-
-Novell, Inc. UnixWare personal edition + SDK
-The Santa Cruz Operation, Inc. A SCO OpenServer + SDK
-Ensoniq Corp, a SoundScape card and extensive amount of assistance
-MediaTrix Peripherals Inc, a AudioTrix Pro card + SDK
-Acer, Inc. a pair of AcerMagic S23 cards.
-
-In addition the following companies have provided me sufficient amount
-of technical information at least some of their products (free or $$$):
-
-Advanced Gravis Computer Technology Ltd.
-Media Vision Inc.
-Analog Devices Inc.
-Logitech Inc.
-Aztech Labs Inc.
-Crystal Semiconductor Corporation,
-Integrated Circuit Systems Inc.
-OAK Technology
-OPTi
-Turtle Beach
-miro
-Ad Lib Inc. ($$)
-Music Quest Inc. ($$)
-Creative Labs ($$$)
-
-If you have some problems
-=========================
-
-Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
-Also look at the home page (http://www.opensound.com/ossfree). It may
-contain info about some recent bug fixes.
-
-It's likely that you have some problems when trying to use the sound driver
-first time. Sound cards don't have standard configuration so there are no
-good default configuration to use. Please try to use same I/O, DMA and IRQ
-values for the sound card than with DOS.
-
-If you get an error message when trying to use the driver, please look
-at /var/adm/messages for more verbose error message.
-
-
-In general the easiest way to diagnose problems is to do "cat /dev/sndstat".
-
-If you get an error message, there are some problems with the driver setup:
-
- - "No such file or directory" tells that the device files for
- the sound driver are missing. Use the script at the end of
- linux/drivers/sound/Readme.linux to create them.
-
- - "No such device" tells that the sound driver is not in the kernel.
- You have to reconfigure and recompile the kernel to have the sound
- driver. Compiling the driver doesn't help alone. You have to boot
- with the newly compiled one before the driver becomes active.
- The Linux-HOWTO should help in this step.
-
-The following errors are likely with /dev/dsp and /dev/audio.
-
- - "No such device or address". This error message should not happen
- with /dev/sndstat but it's possible with the other sound devices.
- This error indicates that there are no suitable hardware for the
- device file or the sound driver has been compiled without support for
- this particular device. For example /dev/audio and /dev/dsp will not
- work if "digitized voice support" was not enabled during "make config".
-
- - "Device or resource busy". Probably the IRQ (or DMA) channel
- required by the sound card is in use by some other device/driver.
-
- - "I/O error". Almost certainly (99%) it's an IRQ or DMA conflict.
- Look at the kernel messages in /var/adm/notice for more info.
-
- - "Invalid argument". The application is calling ioctl()
- with impossible parameters. Check that the application is
- for sound driver version 2.X or later.
-
-In general the printout of /dev/sndstat should tell what is the problem.
-It's possible that there are bugs in the sound driver but 99% of the problems
-reported to me are caused by somehow incorrect setup during "make config".
-
-Best regards,
-
-Hannu
-
-Hannu Savolainen
-ha...@opensound.com
-(Please check http://www.opensound.com/ossfree before mailing me).
-
-Snail mail: Hannu Savolainen
- Hiekkalaiturintie 3 A 8
- 00980 Helsinki
- Finland
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/Readme.cards linux/drivers/sound/Readme.cards
--- v2.2.0-pre7/linux/drivers/sound/Readme.cards Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/Readme.cards Wed Dec 31 16:00:00 1969
@@ -1,1227 +0,0 @@
-Configuring version 3.8 (for Linux) with some common sound cards
-================================================================
-
-This document describes configuring sound cards with the freeware version of
-Open Sound Systems (OSS/Free). Information about the commercial version
-(OSS/Linux) and its configuration is available from
-http://www.opensound.com/linux.html. Information presented here is
-not valid for OSS/Linux.
-
-If you are unsure about how to configure OSS/Free
-you can download the free evaluation version of OSS/Linux from the above
-address. There is a chance that it can autodetect your sound card. In this case
-you can use the information included in soundon.log when configuring OSS/Free.
-
-
-IMPORTANT! This document covers only cards that were "known" when
- this driver version was released. Please look at
- http://www.opensound.com/ossfree for info about
- cards introduced recently.
-
- When configuring the sound driver, you should carefully
- check each sound configuration option (particularly
- "Support for /dev/dsp and /dev/audio"). The default values
- offered by these programs are not necessarily valid.
-
-
-THE BIGGEST MISTAKES YOU CAN MAKE
-=================================
-
-1. Assuming that the card is Sound Blaster compatible when it's not.
---------------------------------------------------------------------
-
-The number one mistake is to assume that your card is compatible with
-Sound Blaster. Only the cards made by Creative Technology or which have
-one or more chips labeled by Creative are SB compatible. In addition there
-are few sound chipsets which are SB compatible in Linux such as ESS1688 or
-Jazz16. Note that SB compatibility in DOS/Windows does _NOT_ mean anything
-in Linux.
-
-IF YOU REALLY ARE 150% SURE YOU HAVE A SOUND BLASTER YOU CAN SKIP THE REST OF
-THIS CHAPTER.
-
-For most other "supposed to be SB compatible" cards you have to use other
-than SB drivers (see below). It is possible to get most sound cards to work
-in SB mode but in general it's a complete waste of time. There are several
-problems which you will encounter by using SB mode with cards that are not
-truly SB compatible:
-
-- The SB emulation is at most SB Pro (DSP version 3.x) which means that
-you get only 8 bit audio (there is always an another ("native") mode which
-gives the 16 bit capability). The 8 bit only operation is the reason why
-many users claim that sound quality in Linux is much worse than in DOS.
-In addition some applications require 16 bit mode and they produce just
-noise with a 8 bit only device.
-- The card may work only in some cases but refuse to work most of the
-time. The SB compatible mode always requires special initialization which is
-done by the DOS/Windows drivers. This kind of cards work in Linux after
-you have warm booted it after DOS but they don't work after cold boot
-(power on or reset).
-- You get the famous "DMA timed out" messages. Usually all SB clones have
-software selectable IRQ and DMA settings. If the (power on default) values
-currently used by the card don't match configuration of the driver you will
-get the above error message whenever you try to record or play. There are
-few other reasons to the DMA timeout message but using the SB mode seems
-to be the most common cause.
-
-2. Trying to use a PnP (Plug & Play) card just like an ordinary sound card
---------------------------------------------------------------------------
-
-Plug & Play is a protocol defined by Intel and Microsoft. It lets operating
-systems to easily identify and reconfigure I/O ports, IRQs and DMAs of ISA
-cards. The problem with PnP cards is that the standard Linux doesn't currently
-(versions 2.1.x and earlier) don't support PnP. This means that you will have
-to use some special tricks (see later) to get a PnP card alive. Many PnP cards
-work after they have been initialized but this is not always the case.
-
-There are sometimes both PnP and non-PnP versions of the same sound card.
-The non-PnP version is the original model which usually has been discontinued
-more than an year ago. The PnP version has the same name but with "PnP"
-appended to it (sometimes not). This causes major confusion since the non-PnP
-model works with Linux but the PnP one doesn't.
-
-You should carefully check if "Plug & Play" or "PnP" is mentioned in the name
-of the card or in the documentation or package that came with the card.
-Everything described in the rest of this document is not necessarily valid for
-PnP models of sound cards even you have managed to wake up the card properly.
-Many PnP cards are simply too different from their non-PnP ancestors which are
-covered by this document.
-
-
-Cards that are not (fully) supported by this driver
-===================================================
-
-See http://www.opensound.com/ossfree for information about sound cards
-to be supported in future.
-
-
-How to use sound without recompiling kernel and/or sound driver
-===============================================================
-
-There is a commercial sound driver which comes in precompiled form and doesn't
-require recompiling of the kernel. See http://www.4Front-tech.com/oss.html for
-more info.
-
-
-Configuring PnP cards
-=====================
-
-New versions of most sound cards use the so-called ISA PnP protocol for
-soft configuring their I/O, IRQ, DMA and shared memory resources.
-Currently at least cards made by Creative Technology (SB32 and SB32AWE
-PnP), Gravis (GUS PnP and GUS PnP Pro), Ensoniq (Soundscape PnP) and
-Aztech (some Sound Galaxy models) use PnP technology. The CS4232/4236 audio
-chip by Crystal Semiconductor (Intel Atlantis, HP Pavilion and many other
-motherboards) is also based on PnP technology but there is a "native" driver
-available for it (see information about CS4232 later in this document).
-
-PnP sound cards (as well as most other PnP ISA cards) are not supported
-by this version of the driver . Proper
-support for them should be released during 97 once the kernel level
-PnP support is available.
-
-There is a method to get most of the PnP cards to work. The basic method
-is the following:
-
-1) Boot DOS so the card's DOS drivers have a chance to initialize it.
-2) _Cold_ boot to Linux by using "loadlin.exe". Hitting ctrl-alt-del
-works with older machines but causes a hard reset of all cards on recent
-(Pentium) machines.
-3) If you have the sound driver in Linux configured properly, the card should
-work now. "Proper" means that I/O, IRQ and DMA settings are the same as in
-DOS. The hard part is to find which settings were used. See the documentation of
-your card for more info.
-
-Windows 95 could work as well as DOS but running loadlin may be difficult.
-Probably you should "shut down" your machine to MS-DOS mode before running it.
-
-Some machines have a BIOS utility for setting PnP resources. This is a good
-way to configure some cards. In this case you don't need to boot DOS/Win95
-before starting Linux.
-
-Another way to initialize PnP cards without DOS/Win95 is a Linux based
-PnP isolation tool. When writing this there is a pre alpha test version
-of such a tool available from ftp://ftp.demon.co.uk/pub/unix/linux/utils. The
-file is called isapnptools-*. Please note that this tool is just a temporary
-solution which may be incompatible with future kernel versions having proper
-support for PnP cards. There are bugs in setting DMA channels in earlier
-versions of isapnptools so at least version 1.6 is required with sound cards.
-
-Yet another way to use PnP cards is to use (commercial) OSS/Linux drivers. See
-http://www.opensound.com/linux.html for more info. This is probably the way you
-should do it if you don't want to spend time recompiling the kernel and
-required tools.
-
-
-Read this before trying to configure the driver
-===============================================
-
-There are currently many cards that work with this driver. Some of the cards
-have native support while others work since they emulate some other
-card (usually SB, MSS/WSS and/or MPU401). The following cards have native
-support in the driver. Detailed instructions for configuring these cards
-will be given later in this document.
-
-Pro Audio Spectrum 16 (PAS16) and compatibles:
- Pro Audio Spectrum 16
- Pro Audio Studio 16
- Logitech Sound Man 16
- NOTE! The original Pro Audio Spectrum as well as the PAS+ are not
- and will not be supported by the driver.
-
-Media Vision Jazz16 based cards
- Pro Sonic 16
- Logitech SoundMan Wave
- (Other Jazz based cards should work but I don't have any reports
- about them).
-
-Sound Blasters
- SB 1.0 to 2.0
- SB Pro
- SB 16
- SB32/64/AWE
- Configure SB32/64/AWE just like SB16. See lowlevel/README.awe
- for information about using the wave table synth.
- NOTE! AWE63/Gold and 16/32/AWE "PnP" cards need to be activated
- using isapnptools before they work with OSS/Free.
- SB16 compatible cards by other manufacturers than Creative.
- You have been fooled since there are _no_ SB16 compatible
- cards on the market (as of May 1997). It's likely that your card
- is compatible just with SB Pro but there is also a non-SB-
- compatible 16 bit mode. Usually it's MSS/WSS but it could also
- be a proprietary one like MV Jazz16 or ESS ES688. OPTi
- MAD16 chips are very common in so called "SB 16 bit cards"
- (try with the MAD16 driver).
-
- ======================================================================
- "Supposed to be SB compatible" cards.
- Forget the SB compatibility and check for other alternatives
- first. The only cards that work with the SB driver in
- Linux have been made by Creative Technology (there is at least
- one chip on the card with "CREATIVE" printed on it). The
- only other SB compatible chips are ESS and Jazz16 chips
- (maybe ALSxxx chips too but they probably don't work).
- Most other "16 bit SB compatible" cards such as "OPTi/MAD16" or
- "Crystal" are _NOT_ SB compatible in Linux.
-
- Practically all sound cards have some kind of SB emulation mode
- in addition to their native (16 bit) mode. In most cases this
- (8 bit only) SB compatible mode doesn't work with Linux. If
- you get it working it may cause problems with games and
- applications which require 16 bit audio. Some 16 bit only
- applications don't check if the card actually supports 16 bits.
- They just dump 16 bit data to a 8 bit card which produces just
- noise.
-
- In most cases the 16 bit native mode is supported by Linux.
- Use the SB mode with "clones" only if you don't find anything
- better from the rest of this doc.
- ======================================================================
-
-Gravis Ultrasound (GUS)
- GUS
- GUS + the 16 bit option
- GUS MAX
- GUS ACE (No MIDI port and audio recording)
- GUS PnP (with RAM)
-
-MPU-401 and compatibles
- The driver works both with the full (intelligent mode) MPU-401
- cards (such as MPU IPC-T and MQX-32M) and with the UART only
- dumb MIDI ports. MPU-401 is currently the most common MIDI
- interface. Most sound cards are compatible with it. However,
- don't enable MPU401 mode blindly. Many cards with native support
- in the driver have their own MPU401 driver. Enabling the standard one
- will cause a conflict with these cards. So check if your card is
- in the list of supported cards before enabling MPU401.
-
-Windows Sound System (MSS/WSS)
- Even when Microsoft has discontinued their own Sound System card
- they managed to make it a standard. MSS compatible cards are based on
- a codec chip which is easily available from at least two manufacturers
- (AD1848 by Analog Devices and CS4231/CS4248 by Crystal Semiconductor).
- Currently most sound cards are based on one of the MSS compatible codec
- chips. The CS4231 is used in the high quality cards such as GUS MAX,
- MediaTrix AudioTrix Pro and TB Tropez (GUS MAX is not MSS compatible).
-
- Having a AD1848, CS4248 or CS4231 codec chip on the card is a good
- sign. Even if the card is not MSS compatible, it could be easy to write
- support for it. Note also that most MSS compatible cards
- require special boot time initialization which may not be present
- in the driver. Also, some MSS compatible cards have native support.
- Enabling the MSS support with these cards is likely to
- cause a conflict. So check if your card is listed in this file before
- enabling the MSS support.
-
-Yamaha FM synthesizers (OPL2, OPL3 (not OPL3-SA) and OPL4)
- Most sound cards have a FM synthesizer chip. The OPL2 is a 2
- operator chip used in the original AdLib card. Currently it's used
- only in the cheapest (8 bit mono) cards. The OPL3 is a 4 operator
- FM chip which provides better sound quality and/or more available
- voices than the OPL2. The OPL4 is a new chip that has an OPL3 and
- a wave table synthesizer packed onto the same chip. The driver supports
- just the OPL3 mode directly. Most cards with an OPL4 (like
- SM Wave and AudioTrix Pro) support the OPL4 mode using MPU401
- emulation. Writing a native OPL4 support is difficult
- since Yamaha doesn't give information about their sample ROM chip.
-
- Enable the generic OPL2/OPL3 FM synthesizer support if your
- card has a FM chip made by Yamaha. Don't enable it if your card
- has a software (TRS) based FM emulator.
-
- ----------------------------------------------------------------
- NOTE! OPL3-SA is different chip than the ordinary OPL3. In addition
- to the FM synth this chip has also digital audio (WSS) and
- MIDI (MPU401) capabilities. Support for OPL3-SA is described below.
- ----------------------------------------------------------------
-
-Yamaha OPL3-SA1
-
- Yamaha OPL3-SA1 (YMF701) is an audio controller chip used on some
- (Intel) motherboards and on cheap sound cards. It should not be
- confused with the original OPL3 chip (YMF278) which is entirely
- different chip. OPL3-SA1 has support for MSS, MPU401 and SB Pro
- (not used in OSS/Free) in addition to the OPL3 FM synth.
-
- There are also chips called OPL3-SA2, OPL3-SA3, ..., OPL3SA-N. They
- are PnP chips and will not work with the OPL3-SA1 driver. You should
- use the standard MSS, MPU401 and OPL3 options with thses chips and to
- activate the card using isapnptools.
-
-4Front Technologies SoftOSS
-
- SoftOSS is a software based wave table emulation which works with
- any 16 bit stereo sound card. Due to its nature a fast CPU is
- required (P133 is minimum). Although SoftOSS does _not_ use MMX
- instructions it has proven out that recent processors (which appear
- to have MMX) perform significantly better with SoftOSS than earlier
- ones. For example a P166MMX beats a PPro200. SoftOSS should not be used
- on 486 or 386 machines.
-
- The amount of CPU load caused by SoftOSS can be controlled by
- selecting the CONFIG_SOFTOSS_RATE and CONFIG_SOFTOSS_VOICES
- parameters properly (they will be prompted by make config). It's
- recommended to set CONFIG_SOFTOSS_VOICES to 32. If you have a
- P166MMX or faster (PPro200 is not faster) you can set
- CONFIG_SOFTOSS_RATE to 44100 (kHz). However with slower systems it
- recommended to use sampling rates around 22050 or even 16000 kHz.
- Selecting too high values for these parameters may hang your
- system when playing MIDI files with hight degree of polyphony
- (number of concurrently playing notes). It's also possible to
- decrease CONFIG_SOFTOSS_VOICES. This makes it possible to use
- higher sampling rates. However using fewer voices decreases
- playback quality more than decreasing the sampling rate.
-
- SoftOSS keeps the samples loaded on the system's RAM so much RAM is
- required. SoftOSS should never be used on machines with less than 16 MB
- of RAM since this is potentially dangerous (you may accidently run out
- of memory which probably crashes the machine).
-
- SoftOSS implements the wave table API originally designed for GUS. For
- this reason all applications designed for GUS should work (at least
- after minor modifications). For example gmod/xgmod and playmidi -g are
- known to work.
-
- To work SoftOSS will require GUS compatible
- patch files to be installed on the system (in /dos/ultrasnd/midi). You
- can use the public domain MIDIA patchset available from several ftp
- sites.
-
- *********************************************************************
- IMPORTANT NOTICE! The original patch set distributed with the Gravis
- Ultrasound card is not in public domain (even though it's available from
- some FTP sites). You should contact Voice Crystal (www.voicecrystal.com)
- if you like to use these patches with SoftOSS included in OSS/Free.
- *********************************************************************
-
-PSS based cards (AD1848 + ADSP-2115 + Echo ESC614 ASIC)
- Analog Devices and Echo Speech have together defined a sound card
- architecture based on the above chips. The DSP chip is used
- for emulation of SB Pro, FM and General MIDI/MT32.
-
- There are several cards based on this architecture. The most known
- ones are Orchid SW32 and Cardinal DSP16.
-
- The driver supports downloading DSP algorithms to these cards.
-
- NOTE! You will have to use the "old" config script when configuring
- PSS cards.
-
-MediaTrix AudioTrix Pro
- The ATP card is built around a CS4231 codec and an OPL4 synthesizer
- chips. The OPL4 mode is supported by a microcontroller running a
- General MIDI emulator. There is also a SB 1.5 compatible playback mode.
-
-Ensoniq SoundScape and compatibles
- Ensoniq has designed a sound card architecture based on the
- OTTO synthesizer chip used in their professional MIDI synthesizers.
- Several companies (including Ensoniq, Reveal and Spea) are selling
- cards based on this architecture.
-
- NOTE! The SoundScape PnP is not supported by OSS/Free. Ensoniq VIVO and
- VIVO90 cards are not compatible with Soundscapes so the Soundscape
- driver will not work with them. You may want to use OSS/Linux with these
- cards.
-
-OPTi MAD16 and Mozart based cards
- The Mozart (OAK OTI-601), MAD16 (OPTi 82C928), MAD16 Pro (OPTi 82C929),
- OPTi 82C924/82C925 (in _non_ PnP mode) and OPTi 82C930 interface
- chips are used in many different sound cards, including some
- cards by Reveal miro and Turtle Beach (Tropez). The purpose of these
- chips is to connect other audio components to the PC bus. The
- interface chip performs address decoding for the other chips.
- NOTE! Tropez Plus is not MAD16 but CS4232 based.
- NOTE! MAD16 PnP cards (82C924, 82C925, 82C931) are not MAD16 compatible
- in the PnP mode. You will have to use them in MSS mode after having
- initialized them using isapnptools or DOS. 82C931 probably requires
- initialization using DOS/Windows (running isapnptools is not enough).
- It's possible to use 82C931 with OSS/Free by jumpering it to non-PnP
- mode (provided that the card has a jumper for this). In non-PnP mode
- 82C931 is compatible with 82C930 and should work with the MAD16 driver
- (without need to use isapnptools or DOS to initialize it). All OPTi
- chips are supported by OSS/Linux (both in PnP and non-PnP modes).
-
-Audio Excel DSP16
- Support for this card was written by Riccardo Faccetti
- (ricc...@cdc8g5.cdc.polimi.it). The AEDSP16 driver included in
- the lowlevel/ directory. To use it you should enable the
- "Additional low level drivers" option.
-
-Crystal CS4232 and CS4236 based cards such as AcerMagic S23, TB Tropez _Plus_ and
- many PC motherboards (Compaq, HP, Intel, ...)
- CS4232 is a PnP multimedia chip which contains a CS3231A codec,
- SB and MPU401 emulations. There is support for OPL3 too.
- Unfortunately the MPU401 mode doesn't work (I don't know how to
- initialize it). CS4236 is an enhanced (compatible) version of CS4232.
- NOTE! Don't ever try to use isapnptools with CS4232 since this will just
- freeze your machine (due to chip bugs). If you have problems in getting
- CS4232 working you could try initializing it with DOS (CS4232C.EXE) and
- then booting Linux using loadlin. CS4232C.EXE loads a secret firmware
- patch which is not documented by Crystal.
-
-Turtle Beach Maui and Tropez "classic"
- This driver version supports sample, patch and program loading commands
- described in the Maui/Tropez User's manual.
- There is now full initialization support too. The audio side of
- the Tropez is based on the MAD16 chip (see above).
- NOTE! Tropez Plus is different card than Tropez "classic" and will not
- work fully in Linux. You can get audio features working by configuring
- the card as a CS4232 based card (above).
-
-
-Jumpers and software configuration
-==================================
-
-Some of the earliest sound cards were jumper configurable. You have to
-configure the driver use I/O, IRQ and DMA settings
-that match the jumpers. Just few 8 bit cards are fully jumper
-configurable (SB 1.x/2.x, SB Pro and clones).
-Some cards made by Aztech have an EEPROM which contains the
-config info. These cards behave much like hardware jumpered cards.
-
-Most cards have jumper for the base I/O address but other parameters
-are software configurable. Sometimes there are few other jumpers too.
-
-Latest cards are fully software configurable or they are PnP ISA
-compatible. There are no jumpers on the board.
-
-The driver handles software configurable cards automatically. Just configure
-the driver to use I/O, IRQ and DMA settings which are known to work.
-You could usually use the same values than with DOS and/or Windows.
-Using different settings is possible but not recommended since it may cause
-some trouble (for example when warm booting from an OS to another or
-when installing new hardware to the machine).
-
-Sound driver sets the soft configurable parameters of the card automatically
-during boot. Usually you don't need to run any extra initialization
-programs when booting Linux but there are some exceptions. See the
-card-specific instructions below for more info.
-
-The drawback of software configuration is that the driver needs to know
-how the card must be initialized. It cannot initialize unknown cards
-even if they are otherwise compatible with some other cards (like SB,
-MPU401 or Windows Sound System).
-
-
-What if your card was not listed above?
-=======================================
-
-The first thing to do is to look at the major IC chips on the card.
-Many of the latest sound cards are based on some standard chips. If you
-are lucky, all of them could be supported by the driver. The most common ones
-are the OPTi MAD16, Mozart, SoundScape (Ensoniq) and the PSS architectures
-listed above. Also look at the end of this file for list of unsupported
-cards and the ones which could be supported later.
-
-The last resort is to send _exact_ name and model information of the card
-to me together with a list of the major IC chips (manufactured, model) to
-me. I could then try to check if your card looks like something familiar.
-
-There are many more cards in the world than listed above. The first thing to
-do with these cards is to check if they emulate some other card or interface
-such as SB, MSS and/or MPU401. In this case there is a chance to get the
-card to work by booting DOS before starting Linux (boot DOS, hit ctrl-alt-del
-and boot Linux without hard resetting the machine). In this method the
-DOS based driver initializes the hardware to use known I/O, IRQ and DMA
-settings. If sound driver is configured to use the same settings, everything
-should work OK.
-
-
-Configuring sound driver (with Linux)
-=====================================
-
-The sound driver is currently distributed as part of the Linux kernel. The
-files are in /usr/src/linux/drivers/sound/.
-
-****************************************************************************
-* ALWAYS USE THE SOUND DRIVER VERSION WHICH IS DISTRIBUTED WITH *
-* THE KERNEL SOURCE PACKAGE YOU ARE USING. SOME ALPHA AND BETA TEST *
-* VERSIONS CAN BE INSTALLED FROM A SEPARATELY DISTRIBUTED PACKAGE *
-* BUT CHECK THAT THE PACKAGE IS NOT MUCH OLDER (OR NEWER) THAN THE *
-* KERNEL YOU ARE USING. IT'S POSSIBLE THAT THE KERNEL/DRIVER *
-* INTERFACE CHANGES BETWEEN KERNEL RELEASES WHICH MAY CAUSE SOME *
-* INCOMPATIBILITY PROBLEMS. *
-* *
-* IN CASE YOU INSTALL A SEPARATELY DISTRIBUTED SOUND DRIVER VERSION, *
-* BE SURE TO REMOVE OR RENAME THE OLD SOUND DRIVER DIRECTORY BEFORE *
-* INSTALLING THE NEW ONE. LEAVING OLD FILES TO THE SOUND DRIVER *
-* DIRECTORY _WILL_ CAUSE PROBLEMS WHEN THE DRIVER IS USED OR *
-* COMPILED. *
-****************************************************************************
-
-To configure the driver, run "make config" in the kernel source directory
-(/usr/src/linux). Answer "y" or "m" to the question about Sound card support
-(after the questions about mouse, CD-ROM, ftape, etc. support). Questions
-about options for sound will then be asked.
-
-After configuring the kernel and sound driver, run "make dep" and compile
-the kernel following instructions in the kernel README.
-
-The sound driver configuration dialog
--------------------------------------
-
-If you already have the sound driver installed, consult a printout of
-"cat /dev/sndstat" when configuring the driver again. It gives the I/O,
-IRQ and DMA settings you used earlier.
-
-Sound configuration starts by making some yes/no questions. Be careful
-when answering to these questions since answering y to a question may
-prevent some later ones from being asked. For example don't answer y to
-the first question (PAS16) if you don't really have a PAS16. Don't enable
-more cards than you really need since they just consume memory. Also
-some drivers (like MPU401) may conflict with your SCSI controller and
-prevent kernel from booting. If you card was in the list of supported
-cards (above), please look at the card specific config instructions


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 11'
echo 'File patch-2.2.0-pre8 is continued in part 12'
echo 12 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part08

#!/bin/sh
# this is part 08 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 08; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

-#define RC_CMD_CONFIG_VALIDATE 0xBB
-#define RC_CMD_CONN_SETUP 0xCA
-#define RC_CMD_DEVICE_ASSIGN 0xB7
-#define RC_CMD_DEVICE_RELEASE 0xB9
-#define RC_CMD_HRT_GET 0xA8
-#define RC_CMD_ADAPTER_CLEAR 0xBE
-#define RC_CMD_ADAPTER_CONNECT 0xC9
-#define RC_CMD_ADAPTER_RESET 0xBD
-#define RC_CMD_LCT_NOTIFY 0xA2
-#define RC_CMD_OUTBOUND_INIT 0xA1
-#define RC_CMD_PATH_ENABLE 0xD3
-#define RC_CMD_PATH_QUIESCE 0xC5
-#define RC_CMD_PATH_RESET 0xD7
-#define RC_CMD_STATIC_MF_CREATE 0xDD
-#define RC_CMD_STATIC_MF_RELEASE 0xDF
-#define RC_CMD_STATUS_GET 0xA0
-#define RC_CMD_SW_DOWNLOAD 0xA9
-#define RC_CMD_SW_UPLOAD 0xAB
-#define RC_CMD_SW_REMOVE 0xAD
-#define RC_CMD_SYS_ENABLE 0xD1
-#define RC_CMD_SYS_MODIFY 0xC1
-#define RC_CMD_SYS_QUIESCE 0xC3
-#define RC_CMD_SYS_TAB_SET 0xA3
-
-
- /* Init Outbound Q status */
-#define RC_CMD_OUTBOUND_INIT_IN_PROGRESS 0x01
-#define RC_CMD_OUTBOUND_INIT_REJECTED 0x02
-#define RC_CMD_OUTBOUND_INIT_FAILED 0x03
-#define RC_CMD_OUTBOUND_INIT_COMPLETE 0x04
-
-
-#define UTIL_NOP 0x00
-
-
-/* RC Get Status State values */
-
-#define ADAPTER_STATE_INITIALIZING 0x01
-#define ADAPTER_STATE_RESET 0x02
-#define ADAPTER_STATE_HOLD 0x04
-#define ADAPTER_STATE_READY 0x05
-#define ADAPTER_STATE_OPERATIONAL 0x08
-#define ADAPTER_STATE_FAILED 0x10
-#define ADAPTER_STATE_FAULTED 0x11
-
-
-/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */
-
-#define RC_REPLY_STATUS_SUCCESS 0x00
-#define RC_REPLY_STATUS_ABORT_DIRTY 0x01
-#define RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
-#define RC_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
-#define RC_REPLY_STATUS_ERROR_DIRTY 0x04
-#define RC_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
-#define RC_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
-#define RC_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x07
-#define RC_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x08
-#define RC_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x09
-#define RC_REPLY_STATUS_TRANSACTION_ERROR 0x0A
-#define RC_REPLY_STATUS_PROGRESS_REPORT 0x80
-
-
-/* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes.*/
-
-#define RC_DS_SUCCESS 0x0000
-#define RC_DS_BAD_KEY 0x0001
-#define RC_DS_CHAIN_BUFFER_TOO_LARGE 0x0002
-#define RC_DS_DEVICE_BUSY 0x0003
-#define RC_DS_DEVICE_LOCKED 0x0004
-#define RC_DS_DEVICE_NOT_AVAILABLE 0x0005
-#define RC_DS_DEVICE_RESET 0x0006
-#define RC_DS_INAPPROPRIATE_FUNCTION 0x0007
-#define RC_DS_INSUFFICIENT_RESOURCE_HARD 0x0008
-#define RC_DS_INSUFFICIENT_RESOURCE_SOFT 0x0009
-#define RC_DS_INVALID_INITIATOR_ADDRESS 0x000A
-#define RC_DS_INVALID_MESSAGE_FLAGS 0x000B
-#define RC_DS_INVALID_OFFSET 0x000C
-#define RC_DS_INVALID_PARAMETER 0x000D
-#define RC_DS_INVALID_REQUEST 0x000E
-#define RC_DS_INVALID_TARGET_ADDRESS 0x000F
-#define RC_DS_MESSAGE_TOO_LARGE 0x0010
-#define RC_DS_MESSAGE_TOO_SMALL 0x0011
-#define RC_DS_MISSING_PARAMETER 0x0012
-#define RC_DS_NO_SUCH_PAGE 0x0013
-#define RC_DS_REPLY_BUFFER_FULL 0x0014
-#define RC_DS_TCL_ERROR 0x0015
-#define RC_DS_TIMEOUT 0x0016
-#define RC_DS_UNKNOWN_ERROR 0x0017
-#define RC_DS_UNKNOWN_FUNCTION 0x0018
-#define RC_DS_UNSUPPORTED_FUNCTION 0x0019
-#define RC_DS_UNSUPPORTED_VERSION 0x001A
-
- /* msg header defines for VersionOffset */
-#define RCMSGVER_1 0x0001
-#define SGL_OFFSET_0 RCMSGVER_1
-#define SGL_OFFSET_4 (0x0040 | RCMSGVER_1)
-#define TRL_OFFSET_5 (0x0050 | RCMSGVER_1)
-#define TRL_OFFSET_6 (0x0060 | RCMSGVER_1)
-
- /* msg header defines for MsgFlags */
-#define MSG_STATIC 0x0100
-#define MSG_64BIT_CNTXT 0x0200
-#define MSG_MULTI_TRANS 0x1000
-#define MSG_FAIL 0x2000
-#define MSG_LAST 0x4000
-#define MSG_REPLY 0x8000
-
- /* normal LAN request message MsgFlags and VersionOffset (0x1041) */
-#define LAN_MSG_REQST (MSG_MULTI_TRANS | SGL_OFFSET_4)
-
- /* minimum size msg */
-#define THREE_WORD_MSG_SIZE 0x00030000
-#define FOUR_WORD_MSG_SIZE 0x00040000
-#define FIVE_WORD_MSG_SIZE 0x00050000
-#define SIX_WORD_MSG_SIZE 0x00060000
-#define SEVEN_WORD_MSG_SIZE 0x00070000
-#define EIGHT_WORD_MSG_SIZE 0x00080000
-#define NINE_WORD_MSG_SIZE 0x00090000
-
-/* Special TID Assignments */
-
-#define ADAPTER_TID 0
-#define HOST_TID 1
-
- /* RedCreek private message codes */
-#define RC_PRIVATE_GET_MAC_ADDR 0x0001/**/ /* OBSOLETE */
-#define RC_PRIVATE_SET_MAC_ADDR 0x0002
-#define RC_PRIVATE_GET_LAN_STATS 0x0003
-#define RC_PRIVATE_GET_LINK_STATUS 0x0004
-#define RC_PRIVATE_SET_LINK_SPEED 0x0005
-#define RC_PRIVATE_SET_IP_AND_MASK 0x0006
-/* #define RC_PRIVATE_GET_IP_AND_MASK 0x0007 */ /* OBSOLETE */
-#define RC_PRIVATE_GET_LINK_SPEED 0x0008
-#define RC_PRIVATE_GET_FIRMWARE_REV 0x0009
-/* #define RC_PRIVATE_GET_MAC_ADDR 0x000A *//**/
-#define RC_PRIVATE_GET_IP_AND_MASK 0x000B /**/
-#define RC_PRIVATE_DEBUG_MSG 0x000C
-#define RC_PRIVATE_REPORT_DRIVER_CAPABILITY 0x000D
-
-#define RC_PRIVATE_REBOOT 0x00FF
-
-
-/* RC message header */
-typedef struct _RC_MSG_FRAME
-{
- U8 VersionOffset;
- U8 MsgFlags;
- U16 MessageSize;
- BF TargetAddress:TID_SZ;
- BF InitiatorAddress:TID_SZ;
- BF Function:FUNCTION_SZ;
- U32 InitiatorContext;
- /* SGL[] */
-}
- RC_MSG_FRAME, *PRC_MSG_FRAME;
-
-
- /* assumed a 16K minus 256 byte space for outbound queue message frames */
-#define MSG_FRAME_SIZE 512
-#define NMBR_MSG_FRAMES 30
-
-/*
-** Message Unit CSR definitions for RedCreek PCI45 board
-*/
-typedef struct tag_rcatu
-{
- volatile unsigned long APICRegSel; /* APIC Register Select */
- volatile unsigned long reserved0;
- volatile unsigned long APICWinReg; /* APIC Window Register */
- volatile unsigned long reserved1;
- volatile unsigned long InMsgReg0; /* inbound message register 0 */
- volatile unsigned long InMsgReg1; /* inbound message register 1 */
- volatile unsigned long OutMsgReg0; /* outbound message register 0 */
- volatile unsigned long OutMsgReg1; /* outbound message register 1 */
- volatile unsigned long InDoorReg; /* inbound doorbell register */
- volatile unsigned long InIntStat; /* inbound interrupt status register */
- volatile unsigned long InIntMask; /* inbound interrupt mask register */
- volatile unsigned long OutDoorReg; /* outbound doorbell register */
- volatile unsigned long OutIntStat; /* outbound interrupt status register */
- volatile unsigned long OutIntMask; /* outbound interrupt mask register */
- volatile unsigned long reserved2;
- volatile unsigned long reserved3;
- volatile unsigned long InQueue; /* inbound queue port */
- volatile unsigned long OutQueue; /* outbound queue port */
- volatile unsigned long reserved4;
- volatile unsigned long reserver5;
- /* RedCreek extension */
- volatile unsigned long EtherMacLow;
- volatile unsigned long EtherMacHi;
- volatile unsigned long IPaddr;
- volatile unsigned long IPmask;
-}
- ATU, *PATU;
-
- /*
- ** typedef PAB
- **
- ** PCI Adapter Block - holds instance specific information and is located
- ** in a reserved space at the start of the message buffer allocated by user.
- */
-typedef struct
-{
- PATU p_atu; /* ptr to ATU register block */
- PU8 pPci45LinBaseAddr;
- PU8 pLinOutMsgBlock;
- U32 outMsgBlockPhyAddr;
- PFNTXCALLBACK pTransCallbackFunc;
- PFNRXCALLBACK pRecvCallbackFunc;
- PFNCALLBACK pRebootCallbackFunc;
- PFNCALLBACK pCallbackFunc;
- U16 ADAPTERState;
- U16 InboundMFrameSize;
-}
- PAB, *PPAB;
-
- /*
- ** in reserved space right after PAB in host memory is area for returning
- ** values from card
- */
-
- /*
- ** Array of pointers to PCI Adapter Blocks.
- ** Indexed by a zero based (0-31) interface number.
- */
-#define MAX_ADAPTERS 32
-static PPAB PCIAdapterBlock[MAX_ADAPTERS] =
-{


- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL

-};
-
-
-/*
-** typedef NICSTAT
-**
-** Data structure for NIC statistics retruned from PCI card. Data copied from
-** here to user allocated RCLINKSTATS (see rclanmtl.h) structure.
-*/
-typedef struct tag_NicStat
-{
- unsigned long TX_good;
- unsigned long TX_maxcol;
- unsigned long TX_latecol;
- unsigned long TX_urun;
- unsigned long TX_crs; /* lost carrier sense */
- unsigned long TX_def; /* transmit deferred */
- unsigned long TX_singlecol; /* single collisions */
- unsigned long TX_multcol;
- unsigned long TX_totcol;
- unsigned long Rcv_good;
- unsigned long Rcv_CRCerr;
- unsigned long Rcv_alignerr;
- unsigned long Rcv_reserr; /* rnr'd pkts */
- unsigned long Rcv_orun;
- unsigned long Rcv_cdt;
- unsigned long Rcv_runt;
- unsigned long dump_status; /* last field directly from the chip */
-}
- NICSTAT, *P_NICSTAT;
-
-
-#define DUMP_DONE 0x0000A005 /* completed statistical dump */
-#define DUMP_CLEAR 0x0000A007 /* completed stat dump and clear counters */
-
-
-static volatile int msgFlag;
-
-
-/* local function prototypes */
-static void ProcessOutboundAdapterMsg(PPAB pPab, U32 phyMsgAddr);
-static int FillAdapterMsgSGLFromTCB(PU32 pMsg, PRCTCB pXmitCntrlBlock);
-static int GetAdapterStatus(PPAB pPab);
-static int SendAdapterOutboundQInitMsg(PPAB pPab);
-static int SendEnableSysMsg(PPAB pPab);
-
-
- /* 1st 100h bytes of message block is reserved for messenger instance */
-#define ADAPTER_BLOCK_RESERVED_SPACE 0x100
-
-/*
-** =========================================================================
-** InitRCApiMsgLayer()
-**
-** Initialize the RedCreek API Module and adapter.
-**
-** Inputs: AdapterID - interface number from 0 to 15
-** pciBaseAddr - virual base address of PCI (set by BIOS)
-** p_msgbuf - virual address to private message block (min. 16K)
-** p_phymsgbuf - physical address of private message block
-** TransmitCallbackFunction - address of transmit callback function
-** ReceiveCallbackFunction - address of receive callback function
-**
-** private message block is allocated by user. It must be in locked pages.
-** p_msgbuf and p_phymsgbuf point to the same location. Must be contigous
-** memory block of a minimum of 16K byte and long word aligned.
-** =========================================================================
-*/
-RC_RETURN
-InitRCApiMsgLayer(U16 AdapterID, U32 pciBaseAddr,

- PU8 p_msgbuf, PU8 p_phymsgbuf,
- PFNTXCALLBACK TransmitCallbackFunction,
- PFNRXCALLBACK ReceiveCallbackFunction,
- PFNCALLBACK RebootCallbackFunction)
-{

- int result;
- PPAB pPab;
-
-#ifdef DEBUG
- kprintf("InitAPI: Adapter:0x%04.4ux ATU:0x%08.8ulx msgbuf:0x%08.8ulx phymsgbuf:0x%08.8ulx\n"
- "TransmitCallbackFunction:0x%08.8ulx ReceiveCallbackFunction:0x%08.8ulx\n",
- AdapterID, pciBaseAddr, p_msgbuf, p_phymsgbuf, TransmitCallbackFunction, ReceiveCallbackFunction);


-#endif /* DEBUG */
-
-

- /* Check if this interface already initialized - if so, shut it down */
- if (PCIAdapterBlock[AdapterID] != NULL)
- {
- printk("PCIAdapterBlock[%d]!=NULL\n", AdapterID);
-// RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
- PCIAdapterBlock[AdapterID] = NULL;
- }
-
- /*
- ** store adapter instance values in adapter block.
- ** Adapter block is at beginning of message buffer
- */
- pPab = (PPAB)p_msgbuf;
-
- pPab->p_atu = (PATU)pciBaseAddr;
- pPab->pPci45LinBaseAddr = (PU8)pciBaseAddr;
-
- /* Set outbound message frame addr - skip over Adapter Block */
- pPab->outMsgBlockPhyAddr = (U32)(p_phymsgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
- pPab->pLinOutMsgBlock = (PU8)(p_msgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
-
- /* store callback function addresses */
- pPab->pTransCallbackFunc = TransmitCallbackFunction;
- pPab->pRecvCallbackFunc = ReceiveCallbackFunction;
- pPab->pRebootCallbackFunc = RebootCallbackFunction;
- pPab->pCallbackFunc = (PFNCALLBACK)NULL;
-
- /*
- ** Initialize API
- */
- result = GetAdapterStatus(pPab);
-
- if (result != RC_RTN_NO_ERROR)
- return result;
-
- if (pPab->ADAPTERState == ADAPTER_STATE_OPERATIONAL)
- {
- printk("pPab->ADAPTERState == op: resetting adapter\n");
- RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
- }
-
- result = SendAdapterOutboundQInitMsg(pPab);
-
- if (result != RC_RTN_NO_ERROR)
- return result;
-
- result = SendEnableSysMsg(pPab);
-
- if (result != RC_RTN_NO_ERROR)
- return result;
-
- PCIAdapterBlock[AdapterID] = pPab;


- return RC_RTN_NO_ERROR;
-}
-

-/*
-** =========================================================================
-** Disable and Enable Adapter interrupts. Adapter interrupts are enabled at Init time
-** but can be disabled and re-enabled through these two function calls.
-** Packets will still be put into any posted received buffers and packets will
-** be sent through RCSendPacket() functions. Disabling Adapter interrupts
-** will prevent hardware interrupt to host even though the outbound Adapter msg
-** queue is not emtpy.
-** =========================================================================
-*/
-#define i960_OUT_POST_Q_INT_BIT 0x0008 /* bit set masks interrupts */
-
-RC_RETURN RCDisableAdapterInterrupts(U16 AdapterID)
-{
- PPAB pPab;
-
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- pPab->p_atu->OutIntMask |= i960_OUT_POST_Q_INT_BIT;


-
- return RC_RTN_NO_ERROR;
-}
-

-RC_RETURN RCEnableAdapterInterrupts(U16 AdapterID)
-{
- PPAB pPab;
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- pPab->p_atu->OutIntMask &= ~i960_OUT_POST_Q_INT_BIT;


-
- return RC_RTN_NO_ERROR;
-
-}
-
-
-/*
-** =========================================================================

-** RCSendPacket()
-** =========================================================================
-*/
-RC_RETURN
-RCSendPacket(U16 AdapterID, U32 InitiatorContext, PRCTCB pTransCtrlBlock)
-{
- U32 msgOffset;
- PU32 pMsg;
- int size;
- PPAB pPab;
-
-#ifdef DEBUG
-kprintf("RCSendPacket()...\n");


-#endif /* DEBUG */
-

- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- /* get Inbound free Q entry - reading from In Q gets free Q entry */
- /* offset to Msg Frame in PCI msg block */
-
- msgOffset = pPab->p_atu->InQueue;
-
- if (msgOffset == 0xFFFFFFFF)
- {
-#ifdef DEBUG
- kprintf("RCSendPacket(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
- return RC_RTN_FREE_Q_EMPTY;
- }
-
- /* calc virual address of msg - virual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
- size = FillAdapterMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
-
- if (size == -1) /* error processing TCB - send NOP msg */
- {
-#ifdef DEBUG
- kprintf("RCSendPacket(): Error Rrocess TCB!\n");
-#endif /* DEBUG */
- pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = UTIL_NOP << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- return RC_RTN_TCB_ERROR;
- }
- else /* send over msg header */
- {
- pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
- pMsg[1] = LAN_PACKET_SEND << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = InitiatorContext;
- pMsg[3] = 0; /* batch reply */
- /* post to Inbound Post Q */
- pPab->p_atu->InQueue = msgOffset;


- return RC_RTN_NO_ERROR;
- }
-}
-
-
-/*
-** =========================================================================

-** RCPostRecvBuffer()
-**
-** inputs: pBufrCntrlBlock - pointer to buffer control block
-**
-** returns TRUE if successful in sending message, else FALSE.
-** =========================================================================
-*/
-RC_RETURN
-RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransCtrlBlock)
-{
- U32 msgOffset;
- PU32 pMsg;
- int size;
- PPAB pPab;
-
-#ifdef DEBUG
-kprintf("RCPostRecvBuffers()...\n");


-#endif /* DEBUG */
-

- /* search for DeviceHandle */
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
-
- /* get Inbound free Q entry - reading from In Q gets free Q entry */
- /* offset to Msg Frame in PCI msg block */
- msgOffset = pPab->p_atu->InQueue;
-
- if (msgOffset == 0xFFFFFFFF)
- {
-#ifdef DEBUG
- kprintf("RCPostRecvBuffers(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
- return RC_RTN_FREE_Q_EMPTY;
-
- }
- /* calc virual address of msg - virual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
- size = FillAdapterMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
-
- if (size == -1) /* error prcessing TCB - send 3 DWORD private msg == NOP */
- {
-#ifdef DEBUG
- kprintf("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", size);
-#endif /* DEBUG */
- pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = UTIL_NOP << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- /* post to Post Q */
- pPab->p_atu->InQueue = msgOffset;
- return RC_RTN_TCB_ERROR;
- }
- else /* send over size msg header */
- {
- pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
- pMsg[1] = LAN_RECEIVE_POST << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
- pMsg[3] = *(PU32)pTransCtrlBlock; /* number of packet buffers */
- /* post to Post Q */
- pPab->p_atu->InQueue = msgOffset;


- return RC_RTN_NO_ERROR;
- }
-}
-
-
-/*
-** =========================================================================

-** RCProcMsgQ()
-**
-** Process outbound message queue until empty.
-** =========================================================================
-*/
-void
-RCProcMsgQ(U16 AdapterID)
-{
- U32 phyAddrMsg;


- PU8 p8Msg;
- PU32 p32;

- U16 count;
- PPAB pPab;
- unsigned char debug_msg[20];
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return;
-
- phyAddrMsg = pPab->p_atu->OutQueue;
-
- while (phyAddrMsg != 0xFFFFFFFF)
- {


- p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
- p32 = (PU32)p8Msg;
-

- //printk(" msg: 0x%x 0x%x \n", p8Msg[7], p32[5]);
-
- /*
- ** Send Packet Reply Msg
- */
- if (LAN_PACKET_SEND == p8Msg[7]) /* function code byte */
- {
- count = *(PU16)(p8Msg+2);
- count -= p8Msg[0] >> 4;
- /* status, count, context[], adapter */
- (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, AdapterID);
- }
- /*
- ** Receive Packet Reply Msg */
- else if (LAN_RECEIVE_POST == p8Msg[7])
- {
-#ifdef DEBUG
- kprintf("RECV_REPLY pPab:0x%08.8ulx p8Msg:0x%08.8ulx p32:0x%08.8ulx\n", pPab, p8Msg, p32);
- kprintf("msg: 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
- p32[0], p32[1], p32[2], p32[3]);
- kprintf(" 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
- p32[4], p32[5], p32[6], p32[7]);
- kprintf(" 0x%08.8ulx:0X%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
- p32[8], p32[9], p32[10], p32[11]);
-#endif
- /* status, count, buckets remaining, packetParmBlock, adapter */
- (*pPab->pRecvCallbackFunc)(p8Msg[19], p8Msg[12], p32[5], p32+6, AdapterID);
-
-
- }
- else if (LAN_RESET == p8Msg[7] || LAN_SHUTDOWN == p8Msg[7])
- {
- if (pPab->pCallbackFunc)
- {
- (*pPab->pCallbackFunc)(p8Msg[19],0,0,AdapterID);
- }
- else
- {
- pPab->pCallbackFunc = (PFNCALLBACK) 1;
- }
- //PCIAdapterBlock[AdapterID] = 0;
- }
- else if (RC_PRIVATE == p8Msg[7])
- {
- //printk("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]);
- switch (p32[5])
- {
- case RC_PRIVATE_DEBUG_MSG:
- msgFlag = 1;
- /*printk("Received RC_PRIVATE msg\n");*/
- debug_msg[15] = (p32[6]&0xff000000) >> 24;
- debug_msg[14] = (p32[6]&0x00ff0000) >> 16;
- debug_msg[13] = (p32[6]&0x0000ff00) >> 8;
- debug_msg[12] = (p32[6]&0x000000ff);
-
- debug_msg[11] = (p32[7]&0xff000000) >> 24;
- debug_msg[10] = (p32[7]&0x00ff0000) >> 16;
- debug_msg[ 9] = (p32[7]&0x0000ff00) >> 8;
- debug_msg[ 8] = (p32[7]&0x000000ff);
-
- debug_msg[ 7] = (p32[8]&0xff000000) >> 24;
- debug_msg[ 6] = (p32[8]&0x00ff0000) >> 16;
- debug_msg[ 5] = (p32[8]&0x0000ff00) >> 8;
- debug_msg[ 4] = (p32[8]&0x000000ff);
-
- debug_msg[ 3] = (p32[9]&0xff000000) >> 24;
- debug_msg[ 2] = (p32[9]&0x00ff0000) >> 16;
- debug_msg[ 1] = (p32[9]&0x0000ff00) >> 8;
- debug_msg[ 0] = (p32[9]&0x000000ff);
-
- debug_msg[16] = '\0';
- printk (debug_msg);
- break;
- case RC_PRIVATE_REBOOT:
- printk("Adapter reboot initiated...\n");
- if (pPab->pRebootCallbackFunc)
- {
- (*pPab->pRebootCallbackFunc)(0,0,0,AdapterID);
- }
- break;
- default:
- printk("Unknown private msg received: 0x%x\n",
- p32[5]);


- break;
- }
- }
-

- /*
- ** Process other Msg's
- */
- else
- {
- ProcessOutboundAdapterMsg(pPab, phyAddrMsg);
- }
-
- /* return MFA to outbound free Q*/
- pPab->p_atu->OutQueue = phyAddrMsg;
-
- /* any more msgs? */
- phyAddrMsg = pPab->p_atu->OutQueue;
- }


-}
-
-
-/*
-** =========================================================================

-** Returns LAN interface statistical counters to space provided by caller at
-** StatsReturnAddr. Returns 0 if success, else RC_RETURN code.
-** This function will call the WaitCallback function provided by
-** user while waiting for card to respond.
-** =========================================================================
-*/
-RC_RETURN
-RCGetLinkStatistics(U16 AdapterID,

- P_RCLINKSTATS StatsReturnAddr,
- PFNWAITCALLBACK WaitCallback)
-{

- U32 msgOffset;
- volatile U32 timeout;
- volatile PU32 pMsg;
- volatile PU32 p32, pReturnAddr;
- P_NICSTAT pStats;
- int i;
- PPAB pPab;
-
-/*kprintf("Get82558Stats() StatsReturnAddr:0x%08.8ulx\n", StatsReturnAddr);*/
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- msgOffset = pPab->p_atu->InQueue;
-
- if (msgOffset == 0xFFFFFFFF)
- {
- #ifdef DEBUG
- kprintf("Get8255XStats(): Inbound Free Q empty!\n");
- #endif
- return RC_RTN_FREE_Q_EMPTY;
- }
-
- /* calc virual address of msg - virual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-/*dprintf("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
-/*dprintf("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
-
- pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
- pMsg[3] = 0x112; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LAN_STATS;
- pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
-
- p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
-
- pStats = (P_NICSTAT)p32;
- pStats->dump_status = 0xFFFFFFFF;
-
- /* post to Inbound Post Q */
- pPab->p_atu->InQueue = msgOffset;
-
- timeout = 100000;
- while (1)
- {
- if (WaitCallback)
- (*WaitCallback)();
-
- for (i = 0; i < 1000; i++)
- ;
-
- if (pStats->dump_status != 0xFFFFFFFF)
- break;
-
- if (!timeout--)
- {
- #ifdef DEBUG
- kprintf("RCGet82558Stats() Timeout waiting for NIC statistics\n");
- #endif
- return RC_RTN_MSG_REPLY_TIMEOUT;
- }
- }
-
- pReturnAddr = (PU32)StatsReturnAddr;
-
- /* copy Nic stats to user's structure */
- for (i = 0; i < (int) sizeof(RCLINKSTATS) / 4; i++)
- pReturnAddr[i] = p32[i];


-
- return RC_RTN_NO_ERROR;
-}
-
-
-/*
-** =========================================================================

-** Get82558LinkStatus()
-** =========================================================================
-*/
-RC_RETURN
-RCGetLinkStatus(U16 AdapterID, PU32 ReturnAddr, PFNWAITCALLBACK WaitCallback)
-{
- U32 msgOffset;
- volatile U32 timeout;
- volatile PU32 pMsg;
- volatile PU32 p32;
- PPAB pPab;
-
-/*kprintf("Get82558LinkStatus() ReturnPhysAddr:0x%08.8ulx\n", ReturnAddr);*/
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- msgOffset = pPab->p_atu->InQueue;
-
- if (msgOffset == 0xFFFFFFFF)
- {
- #ifdef DEBUG
- dprintf("Get82558LinkStatus(): Inbound Free Q empty!\n");
- #endif
- return RC_RTN_FREE_Q_EMPTY;
- }
-
- /* calc virual address of msg - virual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-/*dprintf("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
-/*dprintf("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
-
- pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
- pMsg[3] = 0x112; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS;
- pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
-
- p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
- *p32 = 0xFFFFFFFF;
-
- /* post to Inbound Post Q */
- pPab->p_atu->InQueue = msgOffset;
-
- timeout = 100000;
- while (1)
- {
- U32 i;
-
- if (WaitCallback)
- (*WaitCallback)();
-
- for (i = 0; i < 1000; i++)
- ;
-
- if (*p32 != 0xFFFFFFFF)
- break;
-
- if (!timeout--)
- {
- #ifdef DEBUG
- kprintf("Timeout waiting for link status\n");
- #endif
- return RC_RTN_MSG_REPLY_TIMEOUT;
- }
- }
-
- *ReturnAddr = *p32; /* 1 = up 0 = down */


-
- return RC_RTN_NO_ERROR;
-
-}
-
-/*
-** =========================================================================

-** RCGetMAC()
-**
-** get the MAC address the adapter is listening for in non-promiscous mode.
-** MAC address is in media format.
-** =========================================================================
-*/
-RC_RETURN
-RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback)
-{
- unsigned i, timeout;
- U32 off;
- PU32 p;
- U32 temp[2];
- PPAB pPab;
- PATU p_atu;
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- p_atu = pPab->p_atu;
-
- p_atu->EtherMacLow = 0; /* first zero return data */
- p_atu->EtherMacHi = 0;
-
- off = p_atu->InQueue; /* get addresss of message */
-
- if (0xFFFFFFFF == off)
- return RC_RTN_FREE_Q_EMPTY;
-
- p = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-#ifdef RCDEBUG
- printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n",
- (uint)p_atu, (uint)off, (uint)p);
-#endif /* RCDEBUG */
- /* setup private message */
- p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
- p[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- p[2] = 0; /* initiator context */
- p[3] = 0x218; /* transaction context */
- p[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_MAC_ADDR;
-
-
- p_atu->InQueue = off; /* send it to the device */
-#ifdef RCDEBUG
- printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n",
- (uint)p_atu, (uint)off, (uint)p);
-#endif /* RCDEBUG */
-
- /* wait for the rcpci45 board to update the info */
- timeout = 1000000;
- while (0 == p_atu->EtherMacLow)
- {
- if (WaitCallback)
- (*WaitCallback)();
-
- for (i = 0; i < 1000; i++)
- ;
-
- if (!timeout--)
- {
- printk("rc_getmac: Timeout\n");
- return RC_RTN_MSG_REPLY_TIMEOUT;
- }
- }
-
- /* read the mac address */
- temp[0] = p_atu->EtherMacLow;
- temp[1] = p_atu->EtherMacHi;
- memcpy((char *)mac, (char *)temp, 6);
-
-
-#ifdef RCDEBUG
-// printk("rc_getmac: 0x%X\n", ptr);
-#endif /* RCDEBUG */


-
- return RC_RTN_NO_ERROR;
-}
-
-
-/*
-** =========================================================================

-** RCSetMAC()
-**
-** set MAC address the adapter is listening for in non-promiscous mode.
-** MAC address is in media format.
-** =========================================================================
-*/
-RC_RETURN
-RCSetMAC(U16 AdapterID, PU8 mac)
-{
- U32 off;
- PU32 pMsg;
- PPAB pPab;
-
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- off = pPab->p_atu->InQueue; /* get addresss of message */
-
- if (0xFFFFFFFF == off)
- return RC_RTN_FREE_Q_EMPTY;
-
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
- /* setup private message */
- pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = 0; /* initiator context */
- pMsg[3] = 0x219; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_MAC_ADDR;
- pMsg[5] = *(unsigned *)mac; /* first four bytes */
- pMsg[6] = *(unsigned *)(mac + 4); /* last two bytes */
-
- pPab->p_atu->InQueue = off; /* send it to the device */


-
- return RC_RTN_NO_ERROR ;
-}
-
-
-/*
-** =========================================================================

-** RCSetLinkSpeed()
-**
-** set ethernet link speed.
-** input: speedControl - determines action to take as follows
-** 0 = reset and auto-negotiate (NWay)
-** 1 = Full Duplex 100BaseT
-** 2 = Half duplex 100BaseT
-** 3 = Full Duplex 10BaseT
-** 4 = Half duplex 10BaseT
-** all other values are ignore (do nothing)
-** =========================================================================
-*/
-RC_RETURN
-RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode)
-{
- U32 off;
- PU32 pMsg;
- PPAB pPab;
-
-
- pPab =PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- off = pPab->p_atu->InQueue; /* get addresss of message */
-
- if (0xFFFFFFFF == off)
- return RC_RTN_FREE_Q_EMPTY;
-
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
- /* setup private message */
- pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = 0; /* initiator context */
- pMsg[3] = 0x219; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_LINK_SPEED;
- pMsg[5] = LinkSpeedCode; /* link speed code */
-
- pPab->p_atu->InQueue = off; /* send it to the device */


-
- return RC_RTN_NO_ERROR ;
-}
-

-/*
-** =========================================================================
-** RCGetLinkSpeed()
-**
-** get ethernet link speed.
-**
-** 0 = Unknown
-** 1 = Full Duplex 100BaseT
-** 2 = Half duplex 100BaseT
-** 3 = Full Duplex 10BaseT
-** 4 = Half duplex 10BaseT


-**
-** =========================================================================
-*/
-RC_RETURN

-RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback)
-{
- U32 msgOffset, timeout;
- PU32 pMsg;
- volatile PU32 p32;
- U8 AdapterLinkSpeed;
- PPAB pPab;
-
- pPab =PCIAdapterBlock[AdapterID];
-
-
- msgOffset = pPab->p_atu->InQueue;
-
-
- if (msgOffset == 0xFFFFFFFF)
- {
- kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
- return RC_RTN_FREE_Q_EMPTY;
- }
-
- /* calc virtual address of msg - virtual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
- /* virtual pointer to return buffer - clear first two dwords */
- p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
- p32[0] = 0xff;
-
- /* setup private message */
- pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = 0; /* initiator context */
- pMsg[3] = 0x219; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED;
- /* phys address to return status - area right after PAB */
- pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
-
- /* post to Inbound Post Q */
-
- pPab->p_atu->InQueue = msgOffset;
-
- /* wait for response */
- timeout = 1000000;
- while(1)
- {
- int i;
-
- if (WaitCallback)
- (*WaitCallback)();
-
- for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
- ;
-
- if (p32[0] != 0xff)
- break;
-
- if (!timeout--)
- {
- kprintf("Timeout waiting for link speed from adapter\n");
- kprintf("0x%08.8ulx\n", p32[0]);
- return RC_RTN_NO_LINK_SPEED;
- }
- }
-
- /* get Link speed */
- AdapterLinkSpeed = (U8)((volatile PU8)p32)[0] & 0x0f;
-
- *pLinkSpeedCode= AdapterLinkSpeed;


-
- return RC_RTN_NO_ERROR;
-}
-

-/*
-** =========================================================================
-** RCReportDriverCapability(U16 AdapterID, U32 capability)
-**
-** Currently defined bits:
-** WARM_REBOOT_CAPABLE 0x01
-**
-** =========================================================================
-*/
-RC_RETURN
-RCReportDriverCapability(U16 AdapterID, U32 capability)

-{
- U32 off;
- PU32 pMsg;
- PPAB pPab;
-
- pPab =PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- off = pPab->p_atu->InQueue; /* get addresss of message */
-
- if (0xFFFFFFFF == off)
- return RC_RTN_FREE_Q_EMPTY;
-
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
- /* setup private message */
- pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = 0; /* initiator context */
- pMsg[3] = 0x219; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_REPORT_DRIVER_CAPABILITY;
- pMsg[5] = capability;
-
- pPab->p_atu->InQueue = off; /* send it to the device */


-
- return RC_RTN_NO_ERROR ;
-}
-

-/*
-** =========================================================================
-** RCGetFirmwareVer()
-**
-** Return firmware version in the form "SoftwareVersion : Bt BootVersion"


-**
-** =========================================================================
-*/
-RC_RETURN

-RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback)
-{
- U32 msgOffset, timeout;
- PU32 pMsg;
- volatile PU32 p32;
- PPAB pPab;
-
- pPab =PCIAdapterBlock[AdapterID];
-
- msgOffset = pPab->p_atu->InQueue;
-
-
- if (msgOffset == 0xFFFFFFFF)
- {
- kprintf("RCGetFirmwareVer(): Inbound Free Q empty!\n");
- return RC_RTN_FREE_Q_EMPTY;
- }
-
- /* calc virtual address of msg - virtual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
- /* virtual pointer to return buffer - clear first two dwords */
- p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
- p32[0] = 0xff;
-
- /* setup private message */
- pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = 0; /* initiator context */
- pMsg[3] = 0x219; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV;
- /* phys address to return status - area right after PAB */
- pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
-
-
-
- /* post to Inbound Post Q */
-
- pPab->p_atu->InQueue = msgOffset;
-
-
- /* wait for response */
- timeout = 1000000;
- while(1)
- {
- int i;
-
- if (WaitCallback)
- (*WaitCallback)();
-
- for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
- ;
-
- if (p32[0] != 0xff)
- break;
-
- if (!timeout--)
- {
- kprintf("Timeout waiting for link speed from adapter\n");
- return RC_RTN_NO_FIRM_VER;
- }
- }
-
- strcpy(pFirmString, (PU8)p32);


- return RC_RTN_NO_ERROR;
-}
-

-/*
-** =========================================================================
-** RCResetLANCard()
-**
-** ResourceFlags indicates whether to return buffer resource explicitly
-** to host or keep and reuse.
-** CallbackFunction (if not NULL) is the function to be called when
-** reset is complete.
-** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
-** reset is done (if not NULL).


-**
-** =========================================================================
-*/
-RC_RETURN

-RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
-{
- unsigned long off;
- unsigned long *pMsg;
- PPAB pPab;
- int i;
- long timeout = 0;
-
-
- pPab =PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- off = pPab->p_atu->InQueue; /* get addresss of message */
-
- if (0xFFFFFFFF == off)
- return RC_RTN_FREE_Q_EMPTY;
-
- pPab->pCallbackFunc = CallbackFunction;
-
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
- /* setup message */
- pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = LAN_RESET << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
- pMsg[3] = ResourceFlags << 16; /* resource flags */
-
- pPab->p_atu->InQueue = off; /* send it to the device */
-
- if (CallbackFunction == (PFNCALLBACK)NULL)
- {
- /* call RCProcMsgQ() until something in pPab->pCallbackFunc
- or until timer goes off */
- while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
- {
- RCProcMsgQ(AdapterID);
- for (i = 0; i < 100000; i++) /* please don't hog the bus!!! */
- ;
- timeout++;
- if (timeout > 10000)
- {
- break;
- }
- }
- if (ReturnAddr != (PU32)NULL)
- *ReturnAddr = (U32)pPab->pCallbackFunc;
- }


-
- return RC_RTN_NO_ERROR ;
-}

-/*
-** =========================================================================
-** RCResetAdapter()
-**
-** Send StatusGet Msg, wait for results return directly to buffer.


-**
-** =========================================================================
-*/
-RC_RETURN

-RCResetAdapter(U16 AdapterID)
-{
- U32 msgOffset, timeout;
- PU32 pMsg;
- PPAB pPab;
- volatile PU32 p32;
-
- pPab = PCIAdapterBlock[AdapterID];
- msgOffset = pPab->p_atu->InQueue;
-
- if (msgOffset == 0xFFFFFFFF)
- {
- return RC_RTN_FREE_Q_EMPTY;
- }
-
- /* calc virtual address of msg - virtual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
- pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID;
- pMsg[2] = 0; /* universal context */
- pMsg[3] = 0; /* universal context */
- pMsg[4] = 0; /* universal context */
- pMsg[5] = 0; /* universal context */
- /* phys address to return status - area right after PAB */
- pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
- pMsg[7] = 0;
- pMsg[8] = 1; /* return 1 byte */
-
- /* virual pointer to return buffer - clear first two dwords */
- p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
- p32[0] = 0;
- p32[1] = 0;
-
- /* post to Inbound Post Q */
-
- pPab->p_atu->InQueue = msgOffset;
-
- /* wait for response */
- timeout = 1000000;
- while(1)
- {
- int i;
-
- for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
- ;
-
- if (p32[0] || p32[1])
- break;
-
- if (!timeout--)
- {
- printk("RCResetAdapter timeout\n");
- return RC_RTN_MSG_REPLY_TIMEOUT;
- }


- }
- return RC_RTN_NO_ERROR;
-}
-

-/*
-** =========================================================================
-** RCShutdownLANCard()
-**
-** ResourceFlags indicates whether to return buffer resource explicitly
-** to host or keep and reuse.
-** CallbackFunction (if not NULL) is the function to be called when
-** shutdown is complete.
-** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
-** shutdown is done (if not NULL).


-**
-** =========================================================================
-*/
-RC_RETURN

-RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
-{
- volatile PU32 pMsg;
- U32 off;
- PPAB pPab;
- int i;
- long timeout = 0;
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- off = pPab->p_atu->InQueue; /* get addresss of message */
-
- if (0xFFFFFFFF == off)
- return RC_RTN_FREE_Q_EMPTY;
-
- pPab->pCallbackFunc = CallbackFunction;
-
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
- /* setup message */
- pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = LAN_SHUTDOWN << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
- pMsg[3] = ResourceFlags << 16; /* resource flags */
-
- pPab->p_atu->InQueue = off; /* send it to the device */
-
- if (CallbackFunction == (PFNCALLBACK)NULL)
- {
- /* call RCProcMsgQ() until something in pPab->pCallbackFunc
- or until timer goes off */
- while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
- {
- RCProcMsgQ(AdapterID);
- for (i = 0; i < 100000; i++) /* please don't hog the bus!!! */
- ;
- timeout++;
- if (timeout > 10000)
- {
- break;
- }
- }
- if (ReturnAddr != (PU32)NULL)
- *ReturnAddr = (U32)pPab->pCallbackFunc;


- }
- return RC_RTN_NO_ERROR ;
-}
-
-
-/*
-** =========================================================================

-** RCSetRavlinIPandMask()
-**
-** Set the Ravlin 45/PCI cards IP address and network mask.
-**
-** IP address and mask must be in network byte order.
-** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
-** 0x04030201 and 0x00FFFFFF on a little endian machine.


-**
-** =========================================================================
-*/
-RC_RETURN

-RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask)
-{
- volatile PU32 pMsg;
- U32 off;
- PPAB pPab;
-
- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- off = pPab->p_atu->InQueue; /* get addresss of message */
-
- if (0xFFFFFFFF == off)
- return RC_RTN_FREE_Q_EMPTY;
-
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
- /* setup private message */
- pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = 0; /* initiator context */
- pMsg[3] = 0x219; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK;
- pMsg[5] = ipAddr;
- pMsg[6] = netMask;
-
-
- pPab->p_atu->InQueue = off; /* send it to the device */


- return RC_RTN_NO_ERROR ;
-
-}
-
-/*
-** =========================================================================

-** RCGetRavlinIPandMask()
-**
-** get the IP address and MASK from the card
-**
-** =========================================================================
-*/
-RC_RETURN
-RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask,
- PFNWAITCALLBACK WaitCallback)
-{

- unsigned i, timeout;
- U32 off;
- PU32 pMsg, p32;
- PPAB pPab;
- PATU p_atu;
-
-#ifdef DEBUG
- kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);


-#endif /* DEBUG */
-

- pPab = PCIAdapterBlock[AdapterID];
-
- if (pPab == NULL)
- return RC_RTN_ADPTR_NOT_REGISTERED;
-
- p_atu = pPab->p_atu;
- off = p_atu->InQueue; /* get addresss of message */
-
- if (0xFFFFFFFF == off)
- return RC_RTN_FREE_Q_EMPTY;
-
- p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
- *p32 = 0xFFFFFFFF;
-
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-#ifdef DEBUG
- kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
-#endif /* DEBUG */
- /* setup private message */
- pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
- pMsg[2] = 0; /* initiator context */
- pMsg[3] = 0x218; /* transaction context */
- pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK;
- pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
-
- p_atu->InQueue = off; /* send it to the device */
-#ifdef DEBUG
- kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);


-#endif /* DEBUG */
-

- /* wait for the rcpci45 board to update the info */
- timeout = 100000;
- while (0xffffffff == *p32)
- {
- if (WaitCallback)
- (*WaitCallback)();
-
- for (i = 0; i < 1000; i++)
- ;
-
- if (!timeout--)
- {
- #ifdef DEBUG
- kprintf("RCGetRavlinIPandMask: Timeout\n");
- #endif /* DEBUG */
- return RC_RTN_MSG_REPLY_TIMEOUT;
- }
- }
-
-#ifdef DEBUG
- kprintf("RCGetRavlinIPandMask: after time out\n", \
- "p32[0] (IpAddr) 0x%08.8ulx, p32[1] (IPmask) 0x%08.8ulx\n", p32[0], p32[1]);


-#endif /* DEBUG */
-

- /* send IP and mask to user's space */
- *pIpAddr = p32[0];
- *pNetMask = p32[1];
-
-
-#ifdef DEBUG
- kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);


-#endif /* DEBUG */
-

- return RC_RTN_NO_ERROR;
-}
-
-/*
-** /////////////////////////////////////////////////////////////////////////
-** /////////////////////////////////////////////////////////////////////////
-**
-** local functions
-**
-** /////////////////////////////////////////////////////////////////////////
-** /////////////////////////////////////////////////////////////////////////
-*/
-
-/*
-** =========================================================================
-** SendAdapterOutboundQInitMsg()
-**


-** =========================================================================
-*/
-static int

-SendAdapterOutboundQInitMsg(PPAB pPab)
-{
- U32 msgOffset, timeout, phyOutQFrames, i;
- volatile PU32 pMsg;
- volatile PU32 p32;
-
-
-
- msgOffset = pPab->p_atu->InQueue;
-
-
- if (msgOffset == 0xFFFFFFFF)
- {
-#ifdef DEBUG
- kprintf("SendAdapterOutboundQInitMsg(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
- return RC_RTN_FREE_Q_EMPTY;
- }
-
-
- /* calc virual address of msg - virual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-#ifdef DEBUG
-kprintf("SendAdapterOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);


-#endif /* DEBUG */
-

- pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6;
- pMsg[1] = RC_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID;
- pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
- pMsg[3] = 0x106; /* transaction context */
- pMsg[4] = 4096; /* Host page frame size */
- pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; /* outbound msg frame size and Initcode */
- pMsg[6] = 0xD0000004; /* simple sgl element LE, EOB */
- /* phys address to return status - area right after PAB */
- pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
-
- /* virual pointer to return buffer - clear first two dwords */
- p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
- p32[0] = 0;
-
- /* post to Inbound Post Q */
- pPab->p_atu->InQueue = msgOffset;
-
- /* wait for response */
- timeout = 100000;
- while(1)
- {
- for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
- ;
-
- if (p32[0])
- break;
-
- if (!timeout--)
- {
-#ifdef DEBUG
- kprintf("Timeout wait for InitOutQ InPrgress status from adapter\n");
-#endif /* DEBUG */
- return RC_RTN_NO_STATUS;
- }
- }
-
- timeout = 100000;
- while(1)
- {
- for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
- ;
-
- if (p32[0] == RC_CMD_OUTBOUND_INIT_COMPLETE)
- break;
-
- if (!timeout--)
- {
-#ifdef DEBUG
- kprintf("Timeout wait for InitOutQ Complete status from adapter\n");
-#endif /* DEBUG */
- return RC_RTN_NO_STATUS;
- }
- }
-
- /* load PCI outbound free Q with MF physical addresses */
- phyOutQFrames = pPab->outMsgBlockPhyAddr;
-
- for (i = 0; i < NMBR_MSG_FRAMES; i++)
- {
- pPab->p_atu->OutQueue = phyOutQFrames;
- phyOutQFrames += MSG_FRAME_SIZE;


- }
- return RC_RTN_NO_ERROR;
-}
-
-
-/*
-** =========================================================================

-** GetAdapterStatus()
-**
-** Send StatusGet Msg, wait for results return directly to buffer.
-**


-** =========================================================================
-*/
-static int

-GetAdapterStatus(PPAB pPab)
-{
- U32 msgOffset, timeout;
- PU32 pMsg;
- volatile PU32 p32;
-
-
- msgOffset = pPab->p_atu->InQueue;
- printk("GetAdapterStatus: msg offset = 0x%x\n", msgOffset);
- if (msgOffset == 0xFFFFFFFF)
- {
-#ifdef DEBUG
- kprintf("GetAdapterStatus(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
- return RC_RTN_FREE_Q_EMPTY;
- }
-
- /* calc virual address of msg - virual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
- pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID;
- pMsg[2] = 0; /* universal context */
- pMsg[3] = 0; /* universal context */
- pMsg[4] = 0; /* universal context */
- pMsg[5] = 0; /* universal context */
- /* phys address to return status - area right after PAB */
- pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
- pMsg[7] = 0;
- pMsg[8] = 88; /* return 88 bytes */
-
- /* virual pointer to return buffer - clear first two dwords */
- p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
- p32[0] = 0;
- p32[1] = 0;
-
-#ifdef DEBUG
-kprintf("GetAdapterStatus - pMsg:0x%08.8ulx, msgOffset:0x%08.8ulx, [1]:0x%08.8ulx, [6]:0x%08.8ulx\n",
- pMsg, msgOffset, pMsg[1], pMsg[6]);


-#endif /* DEBUG */
-

- /* post to Inbound Post Q */
- pPab->p_atu->InQueue = msgOffset;
-
-#ifdef DEBUG
-kprintf("Return status to p32 = 0x%08.8ulx\n", p32);


-#endif /* DEBUG */
-

- /* wait for response */
- timeout = 1000000;
- while(1)
- {
- int i;
-
- for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
- ;
-
- if (p32[0] && p32[1])
- break;
-
- if (!timeout--)
- {
-#ifdef DEBUG
- kprintf("Timeout waiting for status from adapter\n");
-kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
-kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
-kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
-#endif /* DEBUG */
- return RC_RTN_NO_STATUS;
- }
- }
-
-#ifdef DEBUG
-kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
-kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
-kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
-#endif /* DEBUG */
- /* get adapter state */
- pPab->ADAPTERState = ((volatile PU8)p32)[10];
- pPab->InboundMFrameSize = ((volatile PU16)p32)[6];
-
-#ifdef DEBUG
- kprintf("adapter state 0x%02.2x InFrameSize = 0x%04.4x\n",
- pPab->ADAPTERState, pPab->InboundMFrameSize);
-#endif /* DEBUG */


- return RC_RTN_NO_ERROR;
-}
-
-
-/*
-** =========================================================================

-** SendEnableSysMsg()
-**
-**


-** =========================================================================
-*/
-static int

-SendEnableSysMsg(PPAB pPab)
-{
- U32 msgOffset; // timeout;
- volatile PU32 pMsg;
-
- msgOffset = pPab->p_atu->InQueue;
-
- if (msgOffset == 0xFFFFFFFF)
- {
-#ifdef DEBUG
- kprintf("SendEnableSysMsg(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
- return RC_RTN_FREE_Q_EMPTY;
- }
-
- /* calc virual address of msg - virual already mapped to physical */
- pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-#ifdef DEBUG
-kprintf("SendEnableSysMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);


-#endif /* DEBUG */
-

- pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
- pMsg[1] = RC_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID;
- pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
- pMsg[3] = 0x110; /* transaction context */
- pMsg[4] = 0x50657465; /* RedCreek Private */


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 08'
echo 'File patch-2.2.0-pre8 is continued in part 09'
echo 09 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part13

#!/bin/sh
# this is part 13 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 13; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

@@ -1332,9 +1085,7 @@
X
X case MDL_ESS:
X DDB(printk("Will use ESS ES688/1688 driver\n"));
- audio_flags = DMA_AUTOMODE;
- format_mask |= AFMT_S16_LE;
- driver = &ess_audio_driver;
+ driver = ess_audio_init (devc, &audio_flags, &format_mask);
X break;
X
X case MDL_SB16:
@@ -1355,17 +1106,17 @@
X driver = &sbpro_audio_driver;
X }
X
- if ((devc->my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
+ if ((devc->dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
X name,driver, sizeof(struct audio_driver),
X audio_flags, format_mask, devc,
X devc->dma8,
- devc->duplex ? devc->dma16 : devc->dma8) < 0))
+ devc->duplex ? devc->dma16 : devc->dma8)) < 0)
X {
X printk(KERN_ERR "Sound Blaster: unable to install audio.\n");
X return;
X }
- audio_devs[devc->my_dev]->mixer_dev = devc->my_mixerdev;
- audio_devs[devc->my_dev]->min_fragment = 5;
+ audio_devs[devc->dev]->mixer_dev = devc->my_mixerdev;
+ audio_devs[devc->dev]->min_fragment = 5;
X }
X
X #endif
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.2.0-pre7/linux/drivers/sound/sb_common.c Fri Jan 8 22:36:11 1999
+++ linux/drivers/sound/sb_common.c Thu Jan 14 22:59:47 1999
@@ -32,6 +32,8 @@
X #include "sb_mixer.h"
X #include "sb.h"
X
+#include "sb_ess.h"
+
X static sb_devc *detected_devc = NULL; /* For communication from probe to init */
X static sb_devc *last_devc = NULL; /* For MPU401 initialization */
X
@@ -91,7 +93,7 @@


X return 0;
X }
X

-static int sb_dsp_get_byte(sb_devc * devc)
+int sb_dsp_get_byte(sb_devc * devc)
X {
X int i;
X
@@ -103,50 +105,18 @@
X return 0xffff;
X }
X
-inline void ess_extended (sb_devc * devc)
-{
- /* Enable extended mode */
-
- sb_dsp_command(devc, 0xc6);
-}
-
-int ess_write(sb_devc * devc, unsigned char reg, unsigned char data)
-{
- /* Write a byte to an extended mode register of ES1688 */
-
- if (!sb_dsp_command(devc, reg))
- return 0;
-
- return sb_dsp_command(devc, data);
-}
-
-int ess_read(sb_devc * devc, unsigned char reg)
-{
-/* Read a byte from an extended mode register of ES1688 */
- if (!sb_dsp_command(devc, 0xc0)) /* Read register command */
- return -1;
-
- if (!sb_dsp_command(devc, reg))
- return -1;
-
- return sb_dsp_get_byte(devc);
-}
-
-static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
+static void sb_intr (sb_devc *devc)
X {
X int status;
X unsigned char src = 0xff;
X
- sb_devc *devc = dev_id;
-
- devc->irq_ok = 1;
X if (devc->model == MDL_SB16)
X {
X src = sb_getmixer(devc, IRQ_STAT); /* Interrupt source register */
X
X #if defined(CONFIG_MIDI)&& defined(CONFIG_UART401)
- if (src & 4)
- uart401intr(devc->irq, devc->midi_irq_cookie, NULL); /* MPU401 interrupt */
+ if (src & 4) /* MPU401 interrupt */
+ uart401intr(devc->irq, devc->midi_irq_cookie, NULL);
X #endif
X
X if (!(src & 3))
@@ -209,6 +179,21 @@
X status = inb(DSP_DATA_AVL16);
X }
X
+static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
+{
+ sb_devc *devc = dev_id;
+
+ devc->irq_ok = 1;
+
+ switch (devc->model) {
+ case MDL_ESS:
+ ess_intr (devc);
+ break;
+ default:
+ sb_intr (devc);
+ break;
+ }
+}
X
X int sb_dsp_reset(sb_devc * devc)
X {
@@ -216,10 +201,11 @@
X
X DEB(printk("Entered sb_dsp_reset()\n"));
X
- if (devc->model == MDL_ESS)
- outb(3, DSP_RESET); /* Reset FIFO too */
- else
- outb(1, DSP_RESET);
+ if (devc->model == MDL_ESS) return ess_dsp_reset (devc);
+
+ /* This is only for non-ESS chips */
+
+ outb(1, DSP_RESET);
X
X udelay(10);
X outb(0, DSP_RESET);
@@ -232,9 +218,9 @@
X DDB(printk("sb: No response to RESET\n"));
X return 0; /* Sorry */
X }
- if (devc->model == MDL_ESS) ess_extended (devc);
X
X DEB(printk("sb_dsp_reset() OK\n"));
+


X return 1;
X }
X

@@ -492,206 +478,6 @@
X #endif
X }
X
-/*
- * ESS technology describes a detection scheme in their docs. It involves
- * fiddling with the bits in certain mixer registers. ess_probe is supposed
- * to help.
- */
-static unsigned int ess_identify (sb_devc * devc);
-
-static int ess_probe (sb_devc * devc, int reg, int xorval)
-{
- int val1, val2, val3;
-
- val1 = sb_getmixer (devc, reg);
- val2 = val1 ^ xorval;
- sb_setmixer (devc, reg, val2);
- val3 = sb_getmixer (devc, reg);
- sb_setmixer (devc, reg, val1);
-
- return (val2 == val3);
-}
-
-static int ess_init(sb_devc * devc, struct address_info *hw_config)
-{
- unsigned char cfg, irq_bits = 0, dma_bits = 0;
- int ess_major = 0, ess_minor = 0;
- int i;
- static char name[100];
-
- /*
- * Try to detect ESS chips.
- */
-
- sb_dsp_command(devc, 0xe7); /* Return identification */
-
- for (i = 1000; i; i--)
- {
- if (inb(DSP_DATA_AVAIL) & 0x80)
- {
- if (ess_major == 0)
- ess_major = inb(DSP_READ);
- else
- {
- ess_minor = inb(DSP_READ);


- break;
- }
- }
- }
-

- if (ess_major == 0)
- return 0;
-
- if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80)
- {
- sprintf(name, "ESS ES488 AudioDrive (rev %d)",
- ess_minor & 0x0f);
- hw_config->name = name;
- devc->model = MDL_SBPRO;
- return 1;
- }
-
- /*
- * This the detection heuristic of ESS technology, though somewhat
- * changed to actually make it work.
- * This results in the following detection steps:
- * - distinct between ES688 and ES1688+ (as always done in this driver)
- * if ES688 we're ready
- * - try to detect ES1868, ES1869 or ES1878 (ess_identify)
- * if successful we're ready
- * - try to detect ES1888, ES1887 or ES1788 (aim: detect ES1887)
- * if successful we're ready
- * - Dunno. Must be 1688. Will do in general
- *
- * This is the most BETA part of the software: Will the detection
- * always work?
- */
- devc->model = MDL_ESS;
- devc->submodel = ess_minor & 0x0f;
-
- if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
- {
- char *chip = NULL;
-
- if ((ess_minor & 0x0f) < 8) {
- chip = "ES688";
- };
- if (chip == NULL) {
- int type;
-
- type = ess_identify (devc);
-
- switch (type) {
- case 0x1868:
- chip = "ES1868";
- devc->submodel = SUBMDL_ES1868;
- break;
- case 0x1869:
- chip = "ES1869";
- devc->submodel = SUBMDL_ES1869;
- break;
- case 0x1878:
- chip = "ES1878";
- devc->submodel = SUBMDL_ES1878;
- break;
- };
- };
- if (chip == NULL && !ess_probe(devc, 0x64, (1 << 3))) {
- if (ess_probe (devc, 0x70, 0x7f)) {
- if (ess_probe (devc, 0x64, (1 << 5))) {
- chip = "ES1887";
- } else {
- chip = "ES1888";
- }
- devc->submodel = SUBMDL_ES188X;
- } else {
- chip = "ES1788";
- devc->submodel = SUBMDL_ES1788;
- }
- };
- if (chip == NULL) {
- chip = "ES1688";
- };
-
- sprintf(name,"ESS %s AudioDrive (rev %d)",
- chip, ess_minor & 0x0f);
- }
- else
- strcpy(name, "Jazz16");
-
- hw_config->name = name;
- sb_dsp_reset(devc); /* Turn on extended mode */
-
- /*
- * Set IRQ configuration register
- */
-
- cfg = 0x50; /* Enable only DMA counter interrupt */
-
- switch (devc->irq)
- {
- case 2:
- case 9:
- irq_bits = 0;
- break;
-
- case 5:
- irq_bits = 1;
- break;
-
- case 7:
- irq_bits = 2;
- break;
-
- case 10:
- irq_bits = 3;


- break;
-
- default:

- irq_bits = 0;
- cfg = 0x10; /* Disable all interrupts */
- printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", devc->irq);


- return 0;
- }
-

- if (!ess_write(devc, 0xb1, cfg | (irq_bits << 2)))
- printk(KERN_ERR "ESS1688: Failed to write to IRQ config register\n");
-
- /*
- * Set DMA configuration register
- */
-
- cfg = 0x50; /* Extended mode DMA enable */
-
- if (devc->dma8 > 3 || devc->dma8 < 0 || devc->dma8 == 2)
- {
- dma_bits = 0;
- cfg = 0x00; /* Disable all DMA */
- printk(KERN_ERR "ESS1688: Invalid DMA %d\n", devc->dma8);
- }
- else
- {
- if (devc->dma8 == 3)
- dma_bits = 3;
- else
- dma_bits = devc->dma8 + 1;
- }
-
- if (!ess_write(devc, 0xb2, cfg | (dma_bits << 2)))
- printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n");
-
- /*
- * Enable joystick and OPL3
- */
-
- cfg = sb_getmixer(devc, 0x40);
- sb_setmixer(devc, 0x40, cfg | 0x03);
- if (devc->submodel >= 8) /* ES1688 */
- devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */
- sb_dsp_reset(devc);
- return 1;
-}
-
X int sb_dsp_detect(struct address_info *hw_config)
X {
X sb_devc sb_info;
@@ -700,7 +486,7 @@
X memset((char *) &sb_info, 0, sizeof(sb_info)); /* Zero everything */
X sb_info.my_mididev = -1;
X sb_info.my_mixerdev = -1;
- sb_info.my_dev = -1;
+ sb_info.dev = -1;
X
X /*
X * Initialize variables
@@ -905,11 +691,18 @@
X break;
X
X case 3: /* SB Pro and most clones */
- if (devc->model == 0)
- {
+ switch (devc->model) {
+ case 0:
X devc->model = hw_config->card_subtype = MDL_SBPRO;
X if (hw_config->name == NULL)
X hw_config->name = "Sound Blaster Pro (8 BIT ONLY)";
+ break;
+ case MDL_ESS:
+ if (!ess_dsp_init(devc, hw_config)) {
+ release_region (hw_config->io_base, 16);
+ return 0;
+ }
+ break;
X }
X break;
X
@@ -931,6 +724,7 @@
X /* Register 0x22 & 0xf0 on ALS100 == 0xf0; on ALS007 it == 0x10. */
X if ((sb_getmixer(devc,0x30) != 0xff) || ((sb_getmixer(devc,0x22) & 0xf0) != 0x10))
X {
+ devc->submodel = SUBMDL_ALS100;
X if (hw_config->name == NULL)
X hw_config->name = "Sound Blaster 16 (ALS-100)";
X }
@@ -1068,7 +862,7 @@
X /* But we have to do it, if UART401 is not detected */
X if (!sbmpu)
X sound_unload_mididev(devc->my_mididev);
- sound_unload_audiodev(devc->my_dev);
+ sound_unload_audiodev(devc->dev);
X }
X kfree(devc);
X }
@@ -1089,20 +883,16 @@
X {
X unsigned long flags;
X
- /* MDB(printk("ESS: write port %x: %x\n", port, value)); */
+ if (devc->model == MDL_ESS) return ess_setmixer (devc, port, value);
X
X save_flags(flags);
X cli();
- if (devc->model == MDL_ESS && port >= 0xa0) {
- /* ess_extended (devc); */
- ess_write (devc, port, value);
- } else {
- outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
-
- udelay(20);
- outb(((unsigned char) (value & 0xff)), MIXER_DATA);
- udelay(20);
- };
+
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+ udelay(20);
+ outb(((unsigned char) (value & 0xff)), MIXER_DATA);
+ udelay(20);
+
X restore_flags(flags);
X }
X
@@ -1111,38 +901,29 @@
X unsigned int val;
X unsigned long flags;
X
+ if (devc->model == MDL_ESS) return ess_getmixer (devc, port);
+
X save_flags(flags);
X cli();
- outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
X
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
X udelay(20);
X val = inb(MIXER_DATA);
X udelay(20);
+
X restore_flags(flags);
X
X return val;
X }
-/*
- * Some PnP chips can be identified by repeatedly reading mixer register 0x40.
- * This is done by ess_identify
- */
-static unsigned int ess_identify (sb_devc * devc)
-{
- unsigned int val;
- unsigned long flags;


X
- save_flags(flags);
- cli();

- outb(((unsigned char) (0x40 & 0xff)), MIXER_ADDR);
-
- udelay(20);
- val = inb(MIXER_DATA) << 8;
- udelay(20);
- val |= inb(MIXER_DATA);
- udelay(20);
- restore_flags(flags);
+void sb_chgmixer
+ (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
X
- return val;
+ value = sb_getmixer(devc, reg);
+ value = (value & ~mask) | (val & mask);
+ sb_setmixer(devc, reg, value);
X }
X
X #ifdef CONFIG_MIDI
@@ -1285,53 +1066,6 @@
X #endif
X outb((control | 0x03), mpu_base + 7); /* xxxxxx11 restarts */
X hw_config->name = "SoundMan Wave";
- return 1;
-}
-
-static int ess_midi_init(sb_devc * devc, struct address_info *hw_config)
-{
- unsigned char cfg, tmp;
-
- cfg = sb_getmixer(devc, 0x40) & 0x03;
-
- if (devc->submodel < 8)
- {
- sb_setmixer(devc, 0x40, cfg | 0x03); /* Enable OPL3 & joystick */
- return 0; /* ES688 doesn't support MPU401 mode */
- }
- tmp = (hw_config->io_base & 0x0f0) >> 4;
-
- if (tmp > 3)
- {
- sb_setmixer(devc, 0x40, cfg);
- return 0;
- }
- cfg |= tmp << 3;
-
- tmp = 1; /* MPU enabled without interrupts */
-
- /* May be shared: if so the value is -ve */
-
- switch(abs(hw_config->irq))
- {
- case 9:
- tmp = 0x4;
- break;
- case 5:
- tmp = 0x5;
- break;
- case 7:
- tmp = 0x6;
- break;
- case 10:
- tmp = 0x7;
- break;
- default:


- return 0;
- }
-

- cfg |= tmp << 5;
- sb_setmixer(devc, 0x40, cfg | 0x03);
X return 1;
X }
X
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/sb_ess.c linux/drivers/sound/sb_ess.c
--- v2.2.0-pre7/linux/drivers/sound/sb_ess.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/sb_ess.c Sun Jan 17 18:25:48 1999
@@ -0,0 +1,1682 @@
+/*
+ * Created: 9-Jan-1999
+ *
+ * TODO: consistency speed calculations!!
+ * what's the sample rate when duplex? Docs contradict.
+ * I broke IRQ detection for non-SMP machines
+ * ????: Did I break MIDI support?
+ *
+ * This files contains ESS chip specifics. It's based on the existing ESS
+ * handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This
+ * file adds features like:
+ * - Chip Identification (as shown in /proc/sound)
+ * - RECLEV support for ES1688 and later
+ * - 6 bits playback level support chips later than ES1688
+ * - Recording level support on a per-device basis for ES1887
+ * - Full-Duplex for ES1887 (under development)
+ *
+ * Full duplex is enabled by specifying dma16. While the normal dma must
+ * be one of 0, 1 or 3, dma16 can be one of 0, 1, 3 or 5. DMA 5 is a 16 bit
+ * DMA channel, while the others are 8 bit..
+ *
+ * History:
+ *
+ * Rolf Fokkens (Dec 20 1998): ES188x recording level support on a per
+ * input basis.
+ * (Dec 24 1998): Recognition of ES1788, ES1887, ES1888,
+ * ES1868, ES1869 and ES1878. Could be used for
+ * specific handling in the future. All except
+ * ES1887 and ES1888 and ES688 are handled like
+ * ES1688.
+ * (Dec 27 1998): RECLEV for all (?) ES1688+ chips. ES188x now
+ * have the "Dec 20" support + RECLEV
+ * (jan 2 1999): Preparation for Full Duplex. This means
+ * Audio 2 is now used for playback when dma16
+ * is specified. The next step would be to use
+ * Audio 1 and Audio 2 at the same time.
+ */
+
+#undef FKS_LOGGING
+
+/*
+ * About the documentation
+ *
+ * I don't know if the chips all are OK, but the documentation is buggy. 'cause
+ * I don't have all the cips myself, there's a lot I cannot verify. I'll try to
+ * keep track of my latest insights about his here. If you have additional info,
+ * please enlighten me (fokk...@vertis.nl)!
+ *
+ * I had the impression that ES1688 also has 6 bit master volume control. The
+ * documentation about ES1888 (rev C, october '95) claims that ES1888 has
+ * the following features ES1688 doesn't have:
+ * - 6 bit master volume
+ * - Full Duplex
+ * So ES1688 apparently doesn't have 6 bit master volume control, but the
+ * ES1688 does have RECLEV control. Makes me wonder: does ES688 have it too?
+ * Without RECLEV ES688 won't be much fun I guess.
+ *
+ * From the ES1888 (rev C, october '95) documentation I got the impression
+ * that registers 0x68 to 0x6e don't exist which means: no recording volume
+ * controls. To my surprise the ES888 documentation (1/14/96) claims that
+ * ES888 does have these record mixer registers, but that ES1888 doesn't have
+ * 0x69 and 0x6b. So the rest should be there.
+ *
+ * I'm trying to get ES1887 Full Duplex. Audio 2 is playback only, while Audio 2
+ * is both record and playback. I think I should use Audio 2 for all playback.
+ *
+ * The documentation is an adventure: it's close but not fully accurate. I
+ * found out that after a reset some registers are *NOT* reset, though the
+ * docs say the would be. Interresting ones are 0x7f, 0x7d and 0x7a. They are
+ * related to the Audio 2 channel. I also was suprised about the consequenses
+ * of writing 0x00 to 0x7f (which should be done by reset): The ES1887 moves
+ * into ES1888 mode. This means that it claims IRQ 11, which happens to be my
+ * ISDN adapter. Needless to say it no longer worked. I now understand why
+ * after rebooting 0x7f already was 0x05, the value of my choise: the BIOS
+ * did it.
+ *
+ * Oh, and this is another trap: in ES1887 docs mixer register 0x70 is decribed
+ * as if it's exactly the same as register 0xa1. This is *NOT* true. The
+ * description of 0x70 in ES1869 docs is accurate however.
+ *
+ * When using audio 2 mixer register 0x72 seems te be meaningless. Only 0xa2
+ * has effect.
+ *
+ * Software reset not being able to reset all registers is great! Especially
+ * the fact that register 0x78 isn't reset is great when you wanna change back
+ * to single dma operation (simplex): audio 2 is still operation, and uses the
+ * same dma as audio 1: your ess changes into a funny echo machine.
+ */
+
+/*
+ * About recognition of ESS chips
+ *
+ * The distinction of ES688, ES1688, ES1788, ES1887 and ES1888 is described in
+ * a (preliminary ??) datasheet on ES1887. It's aim is to identify ES1887, but
+ * during detection the text claims that "this chip may be ..." when a step
+ * fails. This scheme is used to distinct between the above chips.
+ * It appears however that some PnP chips like ES1868 are recognized as ES1788
+ * by the ES1887 detection scheme. These PnP chips can be detected in another
+ * way however: ES1868, ES1869 and ES1878 can be recognized (full proof I think)
+ * by repeatedly reading mixer register 0x40. This is done by ess_identify in
+ * sb_common.c.
+ * This results in the following detection steps:
+ * - distinct between ES688 and ES1688+ (as always done in this driver)
+ * if ES688 we're ready
+ * - try to detect ES1868, ES1869 or ES1878
+ * if successful we're ready
+ * - try to detect ES1888, ES1887 or ES1788
+ * if successful we're ready
+ * - Dunno. Must be 1688. Will do in general
+ *
+ * About RECLEV support:
+ *
+ * The existing ES1688 support didn't take care of the ES1688+ recording
+ * levels very well. Whenever a device was selected (recmask) for recording
+ * it's recording level was loud, and it couldn't be changed. The fact that
+ * internal register 0xb4 could take care of RECLEV, didn't work meaning until
+ * it's value was restored every time the chip was reset; this reset the
+ * value of 0xb4 too. I guess that's what 4front also had (have?) trouble with.
+ *
+ * About ES1887 support:
+ *
+ * The ES1887 has separate registers to control the recording levels, for all
+ * inputs. The ES1887 specific software makes these levels the same as their
+ * corresponding playback levels, unless recmask says they aren't recorded. In
+ * the latter case the recording volumes are 0.
+ * Now recording levels of inputs can be controlled, by changing the playback
+ * levels. Futhermore several devices can be recorded together (which is not
+ * possible with the ES1688.
+ * Besides the separate recording level control for each input, the common
+ * recordig level can also be controlled by RECLEV as described above.
+ *
+ * Not only ES1887 have this recording mixer. I know the following from the
+ * documentation:
+ * ES688 no
+ * ES1688 no
+ * ES1868 no
+ * ES1869 yes
+ * ES1878 no
+ * ES1879 yes
+ * ES1888 no/yes Contradicting documentation; most recent: yes
+ * ES1946 yes This is a PCI chip; not handled by this driver
+ */
+
+#include <linux/delay.h>
+
+#include "sound_config.h"
+#include "sb_mixer.h"
+#include "sb.h"
+
+#include "sb_ess.h"
+
+#ifdef FKS_LOGGING
+static void ess_show_mixerregs (sb_devc *devc);
+#endif
+static int ess_read (sb_devc * devc, unsigned char reg);
+static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data);
+static void ess_chgmixer
+ (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val);
+
+/****************************************************************************
+ * *
+ * ESS audio *
+ * *
+ ****************************************************************************/
+
+struct ess_command {short cmd; short data;};
+
+/*
+ * Commands for initializing Audio 1 for input (record)
+ */
+static struct ess_command ess_i08m[] = /* input 8 bit mono */
+ { {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
+static struct ess_command ess_i16m[] = /* input 16 bit mono */
+ { {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
+static struct ess_command ess_i08s[] = /* input 8 bit stereo */
+ { {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
+static struct ess_command ess_i16s[] = /* input 16 bit stereo */
+ { {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
+
+static struct ess_command *ess_inp_cmds[] =
+ { ess_i08m, ess_i16m, ess_i08s, ess_i16s };
+
+
+/*
+ * Commands for initializing Audio 1 for output (playback)
+ */
+static struct ess_command ess_o08m[] = /* output 8 bit mono */
+ { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
+static struct ess_command ess_o16m[] = /* output 16 bit mono */
+ { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
+static struct ess_command ess_o08s[] = /* output 8 bit stereo */
+ { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
+static struct ess_command ess_o16s[] = /* output 16 bit stereo */
+ { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
+
+static struct ess_command *ess_out_cmds[] =
+ { ess_o08m, ess_o16m, ess_o08s, ess_o16s };
+
+static void ess_exec_commands
+ (sb_devc *devc, struct ess_command *cmdtab[])
+{
+ struct ess_command *cmd;
+
+ cmd = cmdtab [ ((devc->channels != 1) << 1) + (devc->bits != AFMT_U8) ];
+
+ while (cmd->cmd != -1) {
+ ess_write (devc, cmd->cmd, cmd->data);
+ cmd++;
+ }
+}
+
+static void ess_change
+ (sb_devc *devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
+
+ value = ess_read (devc, reg);
+ value = (value & ~mask) | (val & mask);
+ ess_write (devc, reg, value);
+}
+
+static void ess_set_output_parms
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ if (devc->duplex) {
+ devc->trg_buf_16 = buf;
+ devc->trg_bytes_16 = nr_bytes;
+ devc->trg_intrflag_16 = intrflag;
+ devc->irq_mode_16 = IMODE_OUTPUT;
+ } else {
+ devc->trg_buf = buf;
+ devc->trg_bytes = nr_bytes;
+ devc->trg_intrflag = intrflag;
+ devc->irq_mode = IMODE_OUTPUT;
+ }
+}
+
+static void ess_set_input_parms
+ (int dev, unsigned long buf, int count, int intrflag)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ devc->trg_buf = buf;
+ devc->trg_bytes = count;
+ devc->trg_intrflag = intrflag;
+ devc->irq_mode = IMODE_INPUT;
+}
+
+static int ess_calc_div (int clock, int revert, int *speedp, int *diffp)
+{
+ int divider;
+ int speed, diff;
+ int retval;
+
+ speed = *speedp;
+ divider = (clock + speed / 2) / *speedp;
+ retval = revert - divider;
+ if (retval > 127) {
+ retval = 127;
+ divider = revert - retval;
+ }
+ /* This line is suggested. Must be wrong I think
+ *speedp = (clock + divider / 2) / divider;
+ So I chose the next one */
+
+ *speedp = clock / divider;
+ diff = speed - *speedp;
+ if (diff < 0) diff =-diff;
+ *diffp = diff;


+
+ return retval;
+}
+

+static int ess_calc_best_speed
+ (int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp)
+{
+ int speed1 = *speedp, speed2 = *speedp;
+ int div1, div2;
+ int diff1, diff2;
+ int retval;
+
+ div1 = ess_calc_div (clock1, rev1, &speed1, &diff1);
+ div2 = ess_calc_div (clock2, rev2, &speed2, &diff2);
+
+ if (diff1 < diff2) {
+ *divp = div1;
+ *speedp = speed1;
+ retval = 1;
+ } else {
+ *divp = div2;
+ *speedp = speed2;
+ retval = 2;
+ }


+
+ return retval;
+}
+

+/*
+ * Depending on the audiochannel ESS devices can
+ * have different clock settings.
+ * callers of ess_speed only do an audionum suggestion, which means
+ * input suggests 1, output suggests 2. This suggestion is only true
+ * however when doing duplex.
+ */
+static void ess_speed (sb_devc *devc, int audionum)
+{
+ int choice;
+ int speed = devc->speed;
+ int clock1, clock2;
+ int rev1, rev2;
+ int div;
+
+ if (!devc->duplex) audionum = 1;
+
+ if (audionum == 1) {
+ rev1 = 128;
+ clock1 = 397700;
+ rev2 = 256;
+ clock2 = 795500;
+ } else {
+ rev1 = 128;
+ clock1 = 793800;
+ rev2 = 128;
+ clock2 = 768000;
+ }
+ choice = ess_calc_best_speed
+ (clock1, rev1, clock2, rev2, &div, &speed);
+
+#ifdef FKS_REG_LOGGING
+printk (KERN_INFO "FKS: ess_speed (%d) b speed = %d, div=%x\n", audionum, speed, div);
+#endif
+
+ if (choice == 2) div |= 0x80;
+
+ if (audionum == 1) {
+ /* Change behaviour of register A1 *
+ sb_chg_mixer(devc, 0x71, 0x20, 0x20)
+ * For ES1869 only??? */
+ ess_write (devc, 0xa1, div);
+ } else {
+ ess_setmixer (devc, 0x70, div);
+ }
+
+ /* Set filter roll-off to 90% of speed/2 */
+ speed = (speed * 9) / 20;
+
+ div = 256 - 7160000 / (speed * 82);
+
+ if (audionum == 1) {
+ ess_write (devc, 0xa2, div);
+ } else {
+ ess_write (devc, 0xa2, div);
+ ess_setmixer (devc, 0x72, div);
+ }
+}
+
+#if 0
+static void ess_speed(sb_devc * devc)
+{
+ int divider;
+ unsigned char bits = 0;
+ int speed = devc->speed;
+
+ if (speed < 4000)
+ speed = 4000;
+ else if (speed > 48000)
+ speed = 48000;
+
+ if (speed > 22000)
+ {
+ bits = 0x80;
+ divider = 256 - (795500 + speed / 2) / speed;
+ }
+ else
+ {
+ divider = 128 - (397700 + speed / 2) / speed;
+ }
+
+ bits |= (unsigned char) divider;
+
+ ess_write (devc, 0xa1, bits);
+
+ /*
+ * Set filter divider register
+ */
+
+ speed = (speed * 9) / 20; /* Set filter roll-off to 90% of speed/2 */
+ divider = 256 - 7160000 / (speed * 82);
+
+ ess_write (devc, 0xa2, divider);
+
+ return;
+}
+#endif
+
+static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ ess_speed(devc, 1);
+
+ sb_dsp_command(devc, DSP_CMD_SPKOFF);
+
+ ess_write (devc, 0xb8, 0x0e); /* Auto init DMA mode */
+ ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
+ ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */
+
+ ess_exec_commands (devc, ess_inp_cmds);
+
+ ess_change (devc, 0xb1, 0xf0, 0x50);
+ ess_change (devc, 0xb2, 0xf0, 0x50);
+
+ devc->trigger_bits = 0;


+ return 0;
+}
+

+static int ess_audio_prepare_for_output_audio1 (int dev, int bsize, int bcount)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ sb_dsp_reset(devc);
+ ess_speed(devc, 1);
+ ess_write (devc, 0xb8, 4); /* Auto init DMA mode */
+ ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
+ ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/request) */
+
+ ess_exec_commands (devc, ess_out_cmds);
+
+ ess_change (devc, 0xb1, 0xf0, 0x50); /* Enable DMA */
+ ess_change (devc, 0xb2, 0xf0, 0x50); /* Enable IRQ */
+
+ sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */
+
+ devc->trigger_bits = 0;


+ return 0;
+}
+

+static int ess_audio_prepare_for_output_audio2 (int dev, int bsize, int bcount)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+ unsigned char bits;
+
+ sb_dsp_reset(devc);
+
+ /*
+ * Auto-Initialize:
+ * DMA mode + demand mode (8 bytes/request, yes I want it all!)
+ * But leave 16-bit DMA bit untouched!
+ */
+ ess_chgmixer (devc, 0x78, 0xd0, 0xd0);
+
+ ess_speed(devc, 2);
+
+ /* bits 4:3 on ES1887 represent recording source. Keep them! */
+ bits = ess_getmixer (devc, 0x7a) & 0x18;
+
+ /* Set stereo/mono */
+ if (devc->channels != 1) bits |= 0x02;
+
+ /* Init DACs; UNSIGNED mode for 8 bit; SIGNED mode for 16 bit */
+ if (devc->bits != AFMT_U8) bits |= 0x05; /* 16 bit */
+
+ /* Enable DMA, IRQ will be shared (hopefully)*/
+ bits |= 0x60;
+
+ ess_setmixer (devc, 0x7a, bits);
+
+ ess_mixer_reload (devc, SOUND_MIXER_PCM); /* There be sound! */
+
+ devc->trigger_bits = 0;


+ return 0;
+}
+

+static int ess_audio_prepare_for_output(int dev, int bsize, int bcount)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "ess_audio_prepare_for_output: dma_out=%d,dma_in=%d\n"
+, audio_devs[dev]->dmap_out->dma, audio_devs[dev]->dmap_in->dma);
+#endif
+
+ if (devc->duplex) {
+ return ess_audio_prepare_for_output_audio2 (dev, bsize, bcount);
+ } else {
+ return ess_audio_prepare_for_output_audio1 (dev, bsize, bcount);
+ }
+}
+
+static void ess_audio_halt_xfer(int dev)


+{
+ unsigned long flags;

+ sb_devc *devc = audio_devs[dev]->devc;
+
+ save_flags(flags);
+ cli();
+ sb_dsp_reset(devc);
+ restore_flags(flags);
+
+ /*
+ * Audio 2 may still be operational! Creates awful sounds!
+ */
+ if (devc->duplex) ess_chgmixer(devc, 0x78, 0x03, 0x00);
+}
+
+static void ess_audio_start_input
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ int count = nr_bytes;
+ sb_devc *devc = audio_devs[dev]->devc;
+ short c = -nr_bytes;
+
+ /*
+ * Start a DMA input to the buffer pointed by dmaqtail
+ */
+
+ if (audio_devs[dev]->dmap_in->dma > 3) count >>= 1;
+ count--;
+
+ devc->irq_mode = IMODE_INPUT;
+
+ ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
+ ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
+
+ ess_change (devc, 0xb8, 0x0f, 0x0f); /* Go */
+ devc->intr_active = 1;
+}
+
+static void ess_audio_output_block_audio1
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ int count = nr_bytes;
+ sb_devc *devc = audio_devs[dev]->devc;
+ short c = -nr_bytes;
+
+ if (audio_devs[dev]->dmap_out->dma > 3)
+ count >>= 1;
+ count--;
+
+ devc->irq_mode = IMODE_OUTPUT;
+
+ ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
+ ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
+
+ ess_change (devc, 0xb8, 0x05, 0x05); /* Go */
+ devc->intr_active = 1;
+}
+
+static void ess_audio_output_block_audio2
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ int count = nr_bytes;
+ sb_devc *devc = audio_devs[dev]->devc;
+ short c = -nr_bytes;
+
+ if (audio_devs[dev]->dmap_out->dma > 3) count >>= 1;
+ count--;
+
+ ess_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff));
+ ess_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff));
+ ess_chgmixer (devc, 0x78, 0x03, 0x03); /* Go */
+
+ devc->irq_mode_16 = IMODE_OUTPUT;
+ devc->intr_active_16 = 1;
+}
+
+static void ess_audio_output_block
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ if (devc->duplex) {
+ ess_audio_output_block_audio2 (dev, buf, nr_bytes, intrflag);
+ } else {
+ ess_audio_output_block_audio1 (dev, buf, nr_bytes, intrflag);
+ }
+}
+
+/*
+ * FKS: the if-statements for both bits and bits_16 are quite alike.
+ * Combine this...
+ */
+static void ess_audio_trigger(int dev, int bits)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ int bits_16 = bits & devc->irq_mode_16;
+ bits &= devc->irq_mode;
+
+ if (!bits && !bits_16) {
+ /* FKS oh oh.... wrong?? for dma 16? */
+ sb_dsp_command(devc, 0xd0); /* Halt DMA */
+ }
+
+ if (bits) {
+ switch (devc->irq_mode)
+ {
+ case IMODE_INPUT:
+ ess_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
+ devc->trg_intrflag);
+ break;
+
+ case IMODE_OUTPUT:
+ ess_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
+ devc->trg_intrflag);


+ break;
+ }
+ }
+

+ if (bits_16) {
+ switch (devc->irq_mode_16) {
+ case IMODE_INPUT:
+ ess_audio_start_input(dev, devc->trg_buf_16, devc->trg_bytes_16,
+ devc->trg_intrflag_16);
+ break;
+
+ case IMODE_OUTPUT:
+ ess_audio_output_block(dev, devc->trg_buf_16, devc->trg_bytes_16,
+ devc->trg_intrflag_16);


+ break;
+ }
+ }
+

+ devc->trigger_bits = bits | bits_16;
+}
+
+/*
+ * FKS: Change this!! it's the old routine!
+ */
+static int ess_audio_set_speed(int dev, int speed)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+ int divider;
+
+ if (speed > 0)
+ {
+ if (speed < 5000)
+ speed = 5000;
+ if (speed > 48000)
+ speed = 48000;
+
+ if (speed > 22000)
+ {
+ divider = (795500 + speed / 2) / speed;
+ speed = (795500 + divider / 2) / divider;
+ }
+ else
+ {
+ divider = (397700 + speed / 2) / speed;
+ speed = (397700 + divider / 2) / divider;
+ }
+ devc->speed = speed;
+ }
+ return devc->speed;
+}
+
+/*
+ * FKS: This is a one-on-one copy of sb1_audio_set_bits
+ */
+static unsigned int ess_audio_set_bits(int dev, unsigned int bits)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ if (bits != 0) {
+ if (bits == AFMT_U8 || bits == AFMT_S16_LE) {
+ devc->bits = bits;
+ } else {
+ devc->bits = AFMT_U8;
+ }
+ }
+
+ return devc->bits;
+}
+
+/*
+ * FKS: This is a one-on-one copy of sbpro_audio_set_channels
+ * (*) Modified it!!
+ */
+static short ess_audio_set_channels(int dev, short channels)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ if (channels == 1 || channels == 2) devc->channels = channels;
+
+ return devc->channels;
+}
+
+static struct audio_driver ess_audio_driver = /* ESS ES688/1688 */
+{
+ sb_audio_open,
+ sb_audio_close,
+ ess_set_output_parms,
+ ess_set_input_parms,
+ NULL,
+ ess_audio_prepare_for_input,
+ ess_audio_prepare_for_output,
+ ess_audio_halt_xfer,
+ NULL, /* local_qlen */
+ NULL, /* copy_from_user */
+ NULL,
+ NULL,
+ ess_audio_trigger,
+ ess_audio_set_speed,
+ ess_audio_set_bits,
+ ess_audio_set_channels
+};
+
+/*
+ * ess_audio_init must be called from sb_audio_init
+ */
+struct audio_driver *ess_audio_init
+ (sb_devc *devc, int *audio_flags, int *format_mask)
+{
+ *audio_flags = DMA_AUTOMODE;
+ *format_mask |= AFMT_S16_LE;
+
+ if (devc->duplex) {
+ int tmp_dma;
+ /*
+ * sb_audio_init thinks dma8 is for playback and
+ * dma16 is for record. Not now! So swap them.
+ */
+ tmp_dma = devc->dma16;
+ devc->dma16 = devc->dma8;
+ devc->dma8 = tmp_dma;
+
+ *audio_flags |= DMA_DUPLEX;
+ }
+
+ return &ess_audio_driver;
+}
+
+/****************************************************************************
+ * *
+ * ESS common *
+ * *
+ ****************************************************************************/
+static void ess_handle_channel
+ (char *channel, int dev, int intr_active, unsigned char flag, int irq_mode)
+{
+ if (!intr_active || !flag) return;
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode);
+#endif
+ switch (irq_mode) {
+ case IMODE_OUTPUT:
+ DMAbuf_outputintr (dev, 1);
+ break;
+
+ case IMODE_INPUT:
+ DMAbuf_inputintr (dev);
+ break;
+
+ case IMODE_INIT:


+ break;
+
+ default:

+ /* printk(KERN_WARN "ESS: Unexpected interrupt\n"); */
+ }
+}
+
+/*
+ * FKS: TODO!!! Finish this!
+ *
+ * I think midi stuff uses uart401, without interrupts.
+ * So IMODE_MIDI isn't a value for devc->irq_mode.
+ */
+void ess_intr (sb_devc *devc)
+{
+ int status;
+ unsigned char src;
+
+ if (devc->submodel == SUBMDL_ES1887) {
+ src = ess_getmixer (devc, 0x7f) >> 4;
+ } else {
+ src = 0xff;
+ }
+
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "FKS: sbintr src=%x\n",(int)src);
+#endif
+ ess_handle_channel
+ ( "Audio 1"
+ , devc->dev, devc->intr_active , src & 0x01, devc->irq_mode );
+ ess_handle_channel
+ ( "Audio 2"
+ , devc->dev, devc->intr_active_16, src & 0x02, devc->irq_mode_16);
+ /*
+ * Acknowledge interrupts
+ */
+ if (devc->submodel == SUBMDL_ES1887 && (src & 0x02)) {
+ ess_chgmixer (devc, 0x7a, 0x80, 0x00);
+ }
+
+ if (src & 0x01) {
+ status = inb(DSP_DATA_AVAIL);
+ }
+}
+
+static void ess_extended (sb_devc * devc)
+{
+ /* Enable extended mode */
+
+ sb_dsp_command(devc, 0xc6);
+}
+
+static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data)
+{
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "FKS: write reg %x: %x\n", reg, data);
+#endif
+ /* Write a byte to an extended mode register of ES1688 */
+
+ if (!sb_dsp_command(devc, reg))
+ return 0;
+
+ return sb_dsp_command(devc, data);
+}
+
+static int ess_read (sb_devc * devc, unsigned char reg)
+{
+ /* Read a byte from an extended mode register of ES1688 */
+
+ /* Read register command */
+ if (!sb_dsp_command(devc, 0xc0)) return -1;
+
+ if (!sb_dsp_command(devc, reg )) return -1;
+
+ return sb_dsp_get_byte(devc);
+}
+
+int ess_dsp_reset(sb_devc * devc)
+{
+ int loopc;
+
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "FKS: ess_dsp_reset 1\n");
+ess_show_mixerregs (devc);
+#endif
+
+ DEB(printk("Entered ess_dsp_reset()\n"));
+
+ outb(3, DSP_RESET); /* Reset FIFO too */
+
+ udelay(10);
+ outb(0, DSP_RESET);
+ udelay(30);
+
+ for (loopc = 0; loopc < 1000 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++);
+
+ if (inb(DSP_READ) != 0xAA) {
+ DDB(printk("sb: No response to RESET\n"));
+ return 0; /* Sorry */
+ }
+ ess_extended (devc);
+
+ DEB(printk("sb_dsp_reset() OK\n"));
+
+#ifdef FKS_LOGGING
+printk(KERN_INFO "FKS: dsp_reset 2\n");
+ess_show_mixerregs (devc);
+#endif
+


+ return 1;
+}
+

+static int ess_irq_bits (int irq)
+{
+ switch (irq) {
+ case 2:
+ case 9:
+ return 0;
+
+ case 5:
+ return 1;
+
+ case 7:
+ return 2;
+
+ case 10:
+ return 3;
+
+ default:
+ printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", irq);


+ return -1;
+ }
+}
+

+/*
+ * Set IRQ configuration register for all ESS models
+ */
+static int ess_common_set_irq_hw (sb_devc * devc)
+{
+ int irq_bits;
+
+ if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return 0;
+
+ if (!ess_write (devc, 0xb1, 0x50 | (irq_bits << 2))) {
+ printk(KERN_ERR "ES1688: Failed to write to IRQ config register\n");
+ return 0;
+ }


+ return 1;
+}
+

+/*
+ * I wanna use modern ES1887 mixer irq handling. Funny is the
+ * fact that my BIOS wants the same. But suppose someone's BIOS
+ * doesn't do this!
+ * This is independent of duplex. If there's a 1887 this will
+ * prevent it from going into 1888 mode.
+ */
+static void ess_es1887_set_irq_hw (sb_devc * devc)
+{
+ int irq_bits;
+
+ if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return;
+
+ ess_chgmixer (devc, 0x7f, 0x0f, 0x01 | ((irq_bits + 1) << 1));
+}
+
+static int ess_set_irq_hw (sb_devc * devc)
+{
+ if (devc->submodel == SUBMDL_ES1887) ess_es1887_set_irq_hw (devc);
+
+ return ess_common_set_irq_hw (devc);
+}
+
+static unsigned int ess_identify (sb_devc * devc)
+{
+ unsigned int val;


+ unsigned long flags;
+

+ save_flags(flags);
+ cli();
+ outb(((unsigned char) (0x40 & 0xff)), MIXER_ADDR);
+
+ udelay(20);
+ val = inb(MIXER_DATA) << 8;
+ udelay(20);
+ val |= inb(MIXER_DATA);
+ udelay(20);
+ restore_flags(flags);
+
+ return val;
+}
+
+/*
+ * ESS technology describes a detection scheme in their docs. It involves
+ * fiddling with the bits in certain mixer registers. ess_probe is supposed
+ * to help.
+ *
+ * FKS: tracing shows ess_probe writes wrong value to 0x64. Bit 3 reads 1, but
+ * should be written 0 only. Check this.
+ */
+static int ess_probe (sb_devc * devc, int reg, int xorval)
+{
+ int val1, val2, val3;
+
+ val1 = ess_getmixer (devc, reg);
+ val2 = val1 ^ xorval;
+ ess_setmixer (devc, reg, val2);
+ val3 = ess_getmixer (devc, reg);
+ ess_setmixer (devc, reg, val1);
+
+ return (val2 == val3);
+}
+
+int ess_init(sb_devc * devc, struct address_info *hw_config)
+{
+ unsigned char cfg;
+ int ess_major = 0, ess_minor = 0;
+ int i;
+ static char name[100];
+
+ /*
+ * Try to detect ESS chips.
+ */
+
+ sb_dsp_command(devc, 0xe7); /* Return identification */
+
+ for (i = 1000; i; i--) {
+ if (inb(DSP_DATA_AVAIL) & 0x80) {
+ if (ess_major == 0) {
+ ess_major = inb(DSP_READ);
+ } else {
+ ess_minor = inb(DSP_READ);


+ break;
+ }
+ }
+ }

+
+ if (ess_major == 0) return 0;
+
+ if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) {
+ sprintf(name, "ESS ES488 AudioDrive (rev %d)",
+ ess_minor & 0x0f);
+ hw_config->name = name;
+ devc->model = MDL_SBPRO;
+ return 1;
+ }
+
+ /*
+ * This the detection heuristic of ESS technology, though somewhat
+ * changed to actually make it work.
+ * This results in the following detection steps:
+ * - distinct between ES688 and ES1688+ (as always done in this driver)
+ * if ES688 we're ready
+ * - try to detect ES1868, ES1869 or ES1878 (ess_identify)
+ * if successful we're ready
+ * - try to detect ES1888, ES1887 or ES1788 (aim: detect ES1887)
+ * if successful we're ready
+ * - Dunno. Must be 1688. Will do in general
+ *
+ * This is the most BETA part of the software: Will the detection
+ * always work?
+ */
+ devc->model = MDL_ESS;
+ devc->submodel = ess_minor & 0x0f;
+
+ if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
+ char *chip = NULL;
+
+ if ((ess_minor & 0x0f) < 8) {
+ chip = "ES688";
+ };
+#ifdef FKS_LOGGING
+printk(KERN_INFO "FKS: mixer_reset\n");
+ ess_setmixer (devc, 0x00, 0x00);
+#endif
+ if (chip == NULL) {
+ int type;
+
+ type = ess_identify (devc);
+
+ switch (type) {
+ case 0x1868:
+ chip = "ES1868";
+ devc->submodel = SUBMDL_ES1868;
+ break;
+ case 0x1869:
+ chip = "ES1869";
+ devc->submodel = SUBMDL_ES1869;
+ break;
+ case 0x1878:
+ chip = "ES1878";
+ devc->submodel = SUBMDL_ES1878;
+ break;
+ };
+ };
+ if (chip == NULL && !ess_probe(devc, 0x64, (1 << 3))) {
+ if (ess_probe (devc, 0x70, 0x7f)) {
+ if (ess_probe (devc, 0x64, (1 << 5))) {
+ chip = "ES1887";
+ devc->submodel = SUBMDL_ES1887;
+ } else {
+ chip = "ES1888";
+ devc->submodel = SUBMDL_ES1888;
+ }
+ } else {
+ chip = "ES1788";
+ devc->submodel = SUBMDL_ES1788;
+ }
+ };
+ if (chip == NULL) {
+ chip = "ES1688";
+ };
+
+ sprintf(name,"ESS %s AudioDrive (rev %d)", chip, ess_minor & 0x0f);
+ } else {
+ strcpy(name, "Jazz16");
+ }
+
+ hw_config->name = name;
+ /* FKS: sb_dsp_reset to enable extended mode???? */
+ sb_dsp_reset(devc); /* Turn on extended mode */
+
+ /*
+ * Enable joystick and OPL3
+ */
+ cfg = ess_getmixer (devc, 0x40);
+ ess_setmixer (devc, 0x40, cfg | 0x03);
+ if (devc->submodel >= 8) { /* ES1688 */
+ devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */
+ }
+ sb_dsp_reset (devc);
+
+ /*
+ * This is important! If it's not done, the IRQ probe in sb_dsp_init
+ * may fail.
+ */
+ return ess_set_irq_hw (devc);
+}
+
+static int ess_set_dma_hw(sb_devc * devc)
+{
+ unsigned char cfg, dma_bits = 0, dma16_bits;
+ int dma;
+
+#ifdef FKS_LOGGING
+printk(KERN_INFO "ess_set_dma_hw: dma8=%d,dma16=%d,dup=%d\n"
+, devc->dma8, devc->dma16, devc->duplex);
+#endif
+
+ /*
+ * FKS: It seems as if this duplex flag isn't set yet. Check it.
+ */
+ dma = devc->dma8;
+
+ if (dma > 3 || dma < 0 || dma == 2) {
+ dma_bits = 0;
+ printk(KERN_ERR "ESS1688: Invalid DMA8 %d\n", dma);
+ return 0;
+ } else {
+ /* Extended mode DMA enable */
+ cfg = 0x50;
+
+ if (dma == 3) {
+ dma_bits = 3;
+ } else {
+ dma_bits = dma + 1;
+ }
+ }
+
+ if (!ess_write (devc, 0xb2, cfg | (dma_bits << 2))) {
+ printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n");
+ return 0;
+ }
+
+ if (devc->duplex) {
+ dma = devc->dma16;
+ dma16_bits = 0;
+
+ if (dma >= 0) {
+ switch (dma) {
+ case 0:
+ dma_bits = 0x04;


+ break;
+ case 1:

+ dma_bits = 0x05;
+ break;
+ case 3:
+ dma_bits = 0x06;
+ break;
+ case 5:
+ dma_bits = 0x07;
+ dma16_bits = 0x20;
+ break;
+ default:
+ printk(KERN_ERR "ESS1887: Invalid DMA16 %d\n", dma);
+ return 0;
+ };
+ ess_chgmixer (devc, 0x78, 0x20, dma16_bits);
+ ess_chgmixer (devc, 0x7d, 0x07, dma_bits);
+ }
+ }


+ return 1;
+}
+

+/*
+ * This one is called from sb_dsp_init.
+ *
+ * Return values:
+ * 0: Failed
+ * 1: Succeeded or doesn't apply (not SUBMDL_ES1887)
+ */
+int ess_dsp_init (sb_devc *devc, struct address_info *hw_config)
+{
+ /*
+ * This for ES1887 to run Full Duplex. Actually ES1888
+ * is allowed to do so too. I have no idea yet if this
+ * will work for ES1888 however.
+ *
+ * For SB16 having both dma8 and dma16 means enable
+ * Full Duplex. Let's try this for ES1887 too
+ *
+ */
+ if (devc->submodel == SUBMDL_ES1887) {
+ if (hw_config->dma2 != -1) {
+ devc->dma16 = hw_config->dma2;
+ }
+ /*
+ * devc->duplex initialization is put here, cause
+ * ess_set_dma_hw needs it.
+ */
+ if (devc->dma8 != devc->dma16 && devc->dma16 != -1) {
+ devc->duplex = 1;
+ }
+
+ if (!ess_set_dma_hw (devc)) {
+ free_irq(devc->irq, devc);
+ return 0;
+ }
+ return 1;
+ } else {


+ return -1;
+ }
+}
+

+/****************************************************************************
+ * *
+ * ESS mixer *
+ * *
+ ****************************************************************************/
+
+#define ES688_RECORDING_DEVICES \
+ ( SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD )
+#define ES688_MIXER_DEVICES \
+ ( SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE \
+ | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME \
+ | SOUND_MASK_LINE2 | SOUND_MASK_SPEAKER )
+
+#define ES1688_RECORDING_DEVICES \
+ ( ES688_RECORDING_DEVICES )
+#define ES1688_MIXER_DEVICES \
+ ( ES688_MIXER_DEVICES | SOUND_MASK_RECLEV )
+
+#define ES1887_RECORDING_DEVICES \
+ ( ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 | SOUND_MASK_SYNTH)
+#define ES1887_MIXER_DEVICES \
+ ( ES1688_MIXER_DEVICES )
+
+/*
+ * Mixer registers of ES1887
+ *
+ * These registers specifically take care of recording levels. To make the
+ * mapping from playback devices to recording devices every recording
+ * devices = playback device + ES_REC_MIXER_RECDIFF
+ */
+#define ES_REC_MIXER_RECBASE (SOUND_MIXER_LINE3 + 1)
+#define ES_REC_MIXER_RECDIFF (ES_REC_MIXER_RECBASE - SOUND_MIXER_SYNTH)
+
+#define ES_REC_MIXER_RECSYNTH (SOUND_MIXER_SYNTH + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECPCM (SOUND_MIXER_PCM + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECSPEAKER (SOUND_MIXER_SPEAKER + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECLINE (SOUND_MIXER_LINE + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECMIC (SOUND_MIXER_MIC + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECCD (SOUND_MIXER_CD + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECIMIX (SOUND_MIXER_IMIX + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECRECLEV (SOUND_MIXER_RECLEV + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECIGAIN (SOUND_MIXER_IGAIN + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECOGAIN (SOUND_MIXER_OGAIN + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECLINE1 (SOUND_MIXER_LINE1 + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECLINE2 (SOUND_MIXER_LINE2 + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECLINE3 (SOUND_MIXER_LINE3 + ES_REC_MIXER_RECDIFF)
+
+static mixer_tab es688_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+/*
+ * The ES1688 specifics... hopefully correct...
+ * - 6 bit master volume
+ * I was wrong, ES1888 docs say ES1688 didn't have it.
+ * - RECLEV control
+ * These may apply to ES688 too. I have no idea.
+ */
+static mixer_tab es1688_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+static mixer_tab es1688later_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+/*
+ * This one is for all ESS chips with a record mixer.
+ * It's not used (yet) however
+ */
+static mixer_tab es_rec_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECSPEAKER, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE, 0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECMIC, 0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECCD, 0x6a, 7, 4, 0x6a, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECIMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECRECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+/*
+ * This one is for ES1887. It's little different from es_rec_mix: it
+ * has 0x7c for PCM playback level. This is because ES1887 uses
+ * Audio 2 for playback.
+ */
+static mixer_tab es1887_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x7c, 7, 4, 0x7c, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECSPEAKER, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE, 0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECMIC, 0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECCD, 0x6a, 7, 4, 0x6a, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECIMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECRECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+static int ess_has_rec_mixer (int submodel)
+{
+ switch (submodel) {
+ case SUBMDL_ES1887:
+ return 1;
+ default:
+ return 0;
+ };
+};
+
+#ifdef FKS_LOGGING
+static int ess_mixer_mon_regs[]
+ = { 0x70, 0x71, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7d, 0x7f
+ , 0xa1, 0xa2, 0xa4, 0xa5, 0xa8, 0xa9
+ , 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb9
+ , 0x00};
+
+static void ess_show_mixerregs (sb_devc *devc)
+{
+ int *mp = ess_mixer_mon_regs;
+
+return;
+
+ while (*mp != 0) {
+ printk (KERN_INFO "res (%x)=%x\n", *mp, (int)(ess_getmixer (devc, *mp)));
+ mp++;
+ }
+}
+#endif
+
+void ess_setmixer (sb_devc * devc, unsigned int port, unsigned int value)


+{
+ unsigned long flags;
+

+#ifdef FKS_LOGGING
+printk(KERN_INFO "FKS: write mixer %x: %x\n", port, value);
+#endif
+
+ save_flags(flags);
+ cli();
+ if (port >= 0xa0) {
+ ess_write (devc, port, value);
+ } else {
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+
+ udelay(20);
+ outb(((unsigned char) (value & 0xff)), MIXER_DATA);
+ udelay(20);
+ };
+ restore_flags(flags);
+}
+
+unsigned int ess_getmixer (sb_devc * devc, unsigned int port)
+{
+ unsigned int val;


+ unsigned long flags;
+

+ save_flags(flags);
+ cli();
+
+ if (port >= 0xa0) {
+ val = ess_read (devc, port);
+ } else {
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+
+ udelay(20);
+ val = inb(MIXER_DATA);
+ udelay(20);
+ }
+ restore_flags(flags);
+
+ return val;
+}
+
+static void ess_chgmixer
+ (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
+
+ value = ess_getmixer (devc, reg);
+ value = (value & ~mask) | (val & mask);
+ ess_setmixer (devc, reg, value);
+}
+
+/*
+ * ess_mixer_init must be called from sb_mixer_init
+ */
+void ess_mixer_init (sb_devc * devc)
+{
+ devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
+
+ /*
+ * Take care of ES1887 specifics...
+ */
+ switch (devc->submodel) {
+ case SUBMDL_ES1887:
+ devc->supported_devices = ES1887_MIXER_DEVICES;
+ devc->supported_rec_devices = ES1887_RECORDING_DEVICES;
+#ifdef FKS_LOGGING
+printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex);
+#endif
+ if (devc->duplex) {
+ devc->iomap = &es1887_mix;
+ } else {
+ devc->iomap = &es_rec_mix;
+ }
+ break;
+ default:
+ if (devc->submodel < 8) {
+ devc->supported_devices = ES688_MIXER_DEVICES;
+ devc->supported_rec_devices = ES688_RECORDING_DEVICES;
+ devc->iomap = &es688_mix;
+ } else {
+ /*
+ * es1688 has 4 bits master vol.
+ * later chips have 6 bits (?)
+ */
+ devc->supported_devices = ES1688_MIXER_DEVICES;
+ devc->supported_rec_devices = ES1688_RECORDING_DEVICES;
+ if (devc->submodel < 0x10) {
+ devc->iomap = &es1688_mix;
+ } else {
+ devc->iomap = &es1688later_mix;
+ }


+ }
+ }
+}
+
+/*

+ * Changing playback levels at an ESS chip with record mixer means having to
+ * take care of recording levels of recorded inputs (devc->recmask) too!
+ */
+int ess_mixer_set(sb_devc *devc, int dev, int left, int right)
+{
+ if (ess_has_rec_mixer (devc->submodel) && (devc->recmask & (1 << dev))) {
+ sb_common_mixer_set (devc, dev + ES_REC_MIXER_RECDIFF, left, right);
+ }
+ return sb_common_mixer_set (devc, dev, left, right);
+}
+
+/*
+ * After a sb_dsp_reset extended register 0xb4 (RECLEV) is reset too. After
+ * sb_dsp_reset RECLEV has to be restored. This is where ess_mixer_reload
+ * helps.
+ */
+void ess_mixer_reload (sb_devc *devc, int dev)
+{
+ int left, right, value;
+
+ value = devc->levels[dev];
+ left = value & 0x000000ff;
+ right = (value & 0x0000ff00) >> 8;
+
+ sb_common_mixer_set(devc, dev, left, right);
+}
+
+int es_rec_set_recmask(sb_devc * devc, int mask)
+{
+ int i, i_mask, cur_mask, diff_mask;
+ int value, left, right;
+
+#ifdef FKS_LOGGING
+printk (KERN_INFO "FKS: es_rec_set_recmask mask = %x\n", mask);
+#endif
+ /*
+ * Changing the recmask on an ESS chip with recording mixer means:
+ * (1) Find the differences
+ * (2) For "turned-on" inputs: make the recording level the playback level
+ * (3) For "turned-off" inputs: make the recording level zero
+ */
+ cur_mask = devc->recmask;
+ diff_mask = (cur_mask ^ mask);
+
+ for (i = 0; i < 32; i++) {
+ i_mask = (1 << i);
+ if (diff_mask & i_mask) { /* Difference? (1) */
+ if (mask & i_mask) { /* Turn it on (2) */
+ value = devc->levels[i];
+ left = value & 0x000000ff;
+ right = (value & 0x0000ff00) >> 8;
+ } else { /* Turn it off (3) */
+ left = 0;
+ left = 0;
+ right = 0;
+ }
+ sb_common_mixer_set(devc, i + ES_REC_MIXER_RECDIFF, left, right);
+ }
+ }
+ return mask;
+}
+
+int ess_set_recmask(sb_devc * devc, int *mask)
+{
+ /* This applies to ESS chips with record mixers only! */
+
+ if (ess_has_rec_mixer (devc->submodel)) {
+ *mask = es_rec_set_recmask (devc, *mask);
+ return 1; /* Applied */
+ } else {
+ return 0; /* Not applied */
+ }
+}
+
+/*
+ * ess_mixer_reset must be called from sb_mixer_reset


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 13'
echo 'File patch-2.2.0-pre8 is continued in part 14'
echo 14 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part16

#!/bin/sh
# this is part 16 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 16; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

X
X #define INIT_TSS { \
X 0,0, /* back_link, __blh */ \
@@ -281,6 +281,7 @@
X /* Copy and release all segment info associated with a VM */
X extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm);
X extern void release_segments(struct mm_struct * mm);
+extern void forget_segments(void);
X
X /*
X * FPU lazy state save handling..
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h
--- v2.2.0-pre7/linux/include/asm-i386/semaphore.h Wed Jan 13 15:00:43 1999
+++ linux/include/asm-i386/semaphore.h Mon Jan 18 17:33:46 1999
@@ -23,14 +23,49 @@
X #include <asm/atomic.h>
X #include <asm/spinlock.h>
X
+/*
+ * Semaphores are recursive: we allow the holder process
+ * to recursively do down() operations on a semaphore that
+ * the process already owns. In order to do that, we need
+ * to keep a semaphore-local copy of the owner and the
+ * "depth of ownership".
+ *
+ * NOTE! Nasty memory ordering rules:
+ * - "owner" and "owner_count" may only be modified once you hold the
+ * lock.
+ * - "owner_count" must be written _after_ modifying owner, and
+ * must be read _before_ reading owner. There must be appropriate
+ * write and read barriers to enforce this.
+ *
+ * On an x86, writes are always ordered, so the only enformcement
+ * necessary is to make sure that the owner_depth is written after
+ * the owner value in program order.
+ *
+ * For read ordering guarantees, the semaphore wake_lock spinlock
+ * is already giving us ordering guarantees.
+ *
+ * Other (saner) architectures would use "wmb()" and "rmb()" to
+ * do this in a more obvious manner.
+ */
X struct semaphore {
X atomic_t count;
+ unsigned long owner, owner_depth;
X int waking;
X struct wait_queue * wait;
X };
X
-#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL })
+/*
+ * Because we want the non-contention case to be
+ * fast, we save the stack pointer into the "owner"
+ * field, and to get the true task pointer we have
+ * to do the bit masking. That moves the masking
+ * operation into the slow path.
+ */
+#define semaphore_owner(sem) \
+ ((struct task_struct *)((2*PAGE_MASK) & (sem)->owner))
+
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, 0, 0, NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, 1, 0, NULL })
X
X asmlinkage void __down_failed(void /* special register calling convention */);
X asmlinkage int __down_failed_interruptible(void /* params in registers */);
@@ -59,13 +94,53 @@
X spin_unlock_irqrestore(&semaphore_wake_lock, flags);
X }
X
-static inline int waking_non_zero(struct semaphore *sem)
+/*
+ * NOTE NOTE NOTE!
+ *
+ * We read owner-count _before_ getting the semaphore. This
+ * is important, because the semaphore also acts as a memory
+ * ordering point between reading owner_depth and reading
+ * the owner.
+ *
+ * Why is this necessary? The "owner_depth" essentially protects
+ * us from using stale owner information - in the case that this
+ * process was the previous owner but somebody else is racing to
+ * aquire the semaphore, the only way we can see ourselves as an
+ * owner is with "owner_depth" of zero (so that we know to avoid
+ * the stale value).
+ *
+ * In the non-race case (where we really _are_ the owner), there
+ * is not going to be any question about what owner_depth is.
+ *
+ * In the race case, the race winner will not even get here, because
+ * it will have successfully gotten the semaphore with the locked
+ * decrement operation.
+ *
+ * Basically, we have two values, and we cannot guarantee that either
+ * is really up-to-date until we have aquired the semaphore. But we
+ * _can_ depend on a ordering between the two values, so we can use
+ * one of them to determine whether we can trust the other:
+ *
+ * Cases:
+ * - owner_depth == zero: ignore the semaphore owner, because it
+ * cannot possibly be us. Somebody else may be in the process
+ * of modifying it and the zero may be "stale", but it sure isn't
+ * going to say that "we" are the owner anyway, so who cares?
+ * - owner_depth is non-zero. That means that even if somebody
+ * else wrote the non-zero count value, the write ordering requriement
+ * means that they will have written themselves as the owner, so
+ * if we now see ourselves as an owner we can trust it to be true.
+ */
+static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)


X {
X unsigned long flags;

+ unsigned long owner_depth = sem->owner_depth;
X int ret = 0;
X
X spin_lock_irqsave(&semaphore_wake_lock, flags);
- if (sem->waking > 0) {
+ if (sem->waking > 0 || (owner_depth && semaphore_owner(sem) == tsk)) {
+ sem->owner = (unsigned long) tsk;
+ sem->owner_depth++; /* Don't use the possibly stale value */
X sem->waking--;
X ret = 1;
X }
@@ -86,7 +161,9 @@
X "lock ; "
X #endif
X "decl 0(%0)\n\t"
- "js 2f\n"
+ "js 2f\n\t"
+ "movl %%esp,4(%0)\n"
+ "movl $1,8(%0)\n\t"
X "1:\n"
X ".section .text.lock,\"ax\"\n"
X "2:\tpushl $1b\n\t"
@@ -108,6 +185,8 @@
X #endif
X "decl 0(%1)\n\t"
X "js 2f\n\t"
+ "movl %%esp,4(%1)\n\t"
+ "movl $1,8(%1)\n\t"
X "xorl %0,%0\n"
X "1:\n"
X ".section .text.lock,\"ax\"\n"
@@ -131,6 +210,7 @@
X {
X __asm__ __volatile__(
X "# atomic up operation\n\t"
+ "decl 8(%0)\n\t"
X #ifdef __SMP__
X "lock ; "
X #endif
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h
--- v2.2.0-pre7/linux/include/asm-i386/softirq.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-i386/softirq.h Mon Jan 18 17:33:46 1999
@@ -18,8 +18,9 @@
X
X extern inline void remove_bh(int nr)
X {
- bh_base[nr] = NULL;
X bh_mask &= ~(1 << nr);
+ mb();
+ bh_base[nr] = NULL;
X }
X
X extern inline void mark_bh(int nr)
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-i386/string.h linux/include/asm-i386/string.h
--- v2.2.0-pre7/linux/include/asm-i386/string.h Thu Dec 31 10:29:02 1998
+++ linux/include/asm-i386/string.h Fri Jan 15 00:39:37 1999
@@ -191,7 +191,7 @@
X #define __HAVE_ARCH_STRSTR
X extern inline char * strstr(const char * cs,const char * ct)
X {
-int d0, d1, d2, d3;
+int d0, d1, d2, d3, d4;
X register char * __res;
X __asm__ __volatile__(
X "cld\n\t" \
@@ -213,7 +213,7 @@
X "jne 1b\n\t"
X "xorl %%eax,%%eax\n\t"
X "2:"
- :"=a" (__res), "=&c" (d0), "=&S" (d1), "=&d" (d2), "=&D" (d3) : "0" (0),"1" (0xffffffff),"2" (cs),"g" (ct));
+ :"=a" (__res), "=&c" (d0), "=&S" (d1), "=&d" (d2), "=&D" (d3), "=&g" (d4) : "0" (0),"1" (0xffffffff),"2" (cs),"4" (ct));
X return __res;
X }
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h
--- v2.2.0-pre7/linux/include/asm-m68k/processor.h Tue Jun 23 10:01:28 1998
+++ linux/include/asm-m68k/processor.h Mon Jan 18 09:55:30 1999
@@ -45,7 +45,7 @@
X unsigned char fpstate[FPSTATESIZE]; /* floating point state */
X };
X
-#define INIT_MMAP { &init_mm, 0, 0x40000000, __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED), VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
+#define INIT_MMAP { &init_mm, 0, 0x40000000, NULL, __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED), VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
X
X #define INIT_TSS { \
X sizeof(init_stack) + (unsigned long) init_stack, 0, \
@@ -74,6 +74,7 @@
X
X #define copy_segments(nr, tsk, mm) do { } while (0)
X #define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
X
X /*
X * Free current thread data structures etc..
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- v2.2.0-pre7/linux/include/asm-m68k/semaphore.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-m68k/semaphore.h Thu Jan 14 15:53:25 1999
@@ -38,7 +38,7 @@
X atomic_inc(&sem->waking);
X }
X
-static inline int waking_non_zero(struct semaphore *sem)
+static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
X {
X #ifndef CONFIG_RMW_INSNS
X unsigned long flags;
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- v2.2.0-pre7/linux/include/asm-mips/processor.h Fri Oct 23 22:01:23 1998
+++ linux/include/asm-mips/processor.h Mon Jan 18 09:55:30 1999
@@ -139,8 +139,8 @@
X
X #endif /* !defined (_LANGUAGE_ASSEMBLY) */
X
-#define INIT_MMAP { &init_mm, KSEG0, KSEG1, PAGE_SHARED, \
- VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
+#define INIT_MMAP { &init_mm, KSEG0, KSEG1, NULL, PAGE_SHARED, \
+ VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
X
X #define INIT_TSS { \
X /* \
@@ -178,6 +178,7 @@
X /* Copy and release all segment info associated with a VM */
X #define copy_segments(nr, p, mm) do { } while(0)
X #define release_segments(mm) do { } while(0)
+#define forget_segments() do { } while (0)
X
X /*
X * Return saved PC of a blocked thread.
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h
--- v2.2.0-pre7/linux/include/asm-mips/semaphore.h Fri May 8 23:14:55 1998
+++ linux/include/asm-mips/semaphore.h Thu Jan 14 15:53:25 1999
@@ -43,7 +43,7 @@
X atomic_inc(&sem->waking);
X }
X
-static inline int waking_non_zero(struct semaphore *sem)
+static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
X {
X int ret, tmp;
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.2.0-pre7/linux/include/asm-ppc/processor.h Mon Oct 5 13:13:43 1998
+++ linux/include/asm-ppc/processor.h Mon Jan 18 09:55:30 1999
@@ -286,8 +286,9 @@
X * Note: the vm_start and vm_end fields here should *not*
X * be in kernel space. (Could vm_end == vm_start perhaps?)
X */
-#define INIT_MMAP { &init_mm, 0, 0x1000, \
- PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC }
+#define INIT_MMAP { &init_mm, 0, 0x1000, NULL, \
+ PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \
+ 1, NULL, NULL }
X
X /*
X * Return saved PC of a blocked thread. For now, this is the "user" PC
@@ -299,6 +300,7 @@
X
X #define copy_segments(nr, tsk, mm) do { } while (0)
X #define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
X
X /*
X * NOTE! The task struct and the stack go together
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- v2.2.0-pre7/linux/include/asm-ppc/semaphore.h Sat Aug 16 09:51:09 1997
+++ linux/include/asm-ppc/semaphore.h Thu Jan 14 15:53:25 1999
@@ -37,7 +37,7 @@
X atomic_inc(&sem->waking);
X }
X
-static inline int waking_non_zero(struct semaphore *sem)
+static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
X {
X int ret, tmp;
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v2.2.0-pre7/linux/include/asm-sparc/processor.h Thu Aug 6 14:06:34 1998
+++ linux/include/asm-sparc/processor.h Mon Jan 18 09:55:30 1999
@@ -148,6 +148,7 @@
X
X #define copy_segments(nr, tsk, mm) do { } while (0)
X #define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
X
X #ifdef __KERNEL__
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-sparc/semaphore.h linux/include/asm-sparc/semaphore.h
--- v2.2.0-pre7/linux/include/asm-sparc/semaphore.h Thu May 29 21:53:09 1997
+++ linux/include/asm-sparc/semaphore.h Thu Jan 14 15:53:25 1999
@@ -30,7 +30,7 @@
X restore_flags(flags); \
X } while(0)
X
-#define waking_non_zero(sem) \
+#define waking_non_zero(sem,tsk)\
X ({ unsigned long flags; \
X int ret = 0; \
X save_and_cli(flags); \
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.2.0-pre7/linux/include/asm-sparc64/processor.h Sun Nov 8 14:03:10 1998
+++ linux/include/asm-sparc64/processor.h Mon Jan 18 09:55:31 1999
@@ -208,6 +208,7 @@
X
X #define copy_segments(nr, tsk, mm) do { } while (0)
X #define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
X
X #ifdef __KERNEL__
X /* Allocation and freeing of task_struct and kernel stack. */
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-sparc64/semaphore.h linux/include/asm-sparc64/semaphore.h
--- v2.2.0-pre7/linux/include/asm-sparc64/semaphore.h Sun Nov 8 14:03:10 1998
+++ linux/include/asm-sparc64/semaphore.h Thu Jan 14 15:53:25 1999
@@ -24,7 +24,7 @@
X
X #define wake_one_more(sem) atomic_inc(&sem->waking);
X
-static __inline__ int waking_non_zero(struct semaphore *sem)
+static __inline__ int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
X {
X int ret;
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/cdrom.h linux/include/linux/cdrom.h
--- v2.2.0-pre7/linux/include/linux/cdrom.h Sun Nov 8 14:03:11 1998
+++ linux/include/linux/cdrom.h Mon Jan 18 12:47:33 1999
@@ -5,8 +5,7 @@
X * 1994, 1995 Eberhard Moenkeberg, emo...@gwdg.de
X * 1996 David van Leeuwen, da...@tm.tno.nl
X * 1997, 1998 Erik Andersen, ande...@debian.org
- * 1998 Jens Axboe, ax...@image.dk and
- * Chris Zwilling, ch...@cloudnet.com
+ * 1998, 1999 Jens Axboe, ax...@image.dk
X */
X
X #ifndef _LINUX_CDROM_H
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/dcache.h linux/include/linux/dcache.h
--- v2.2.0-pre7/linux/include/linux/dcache.h Thu Dec 31 10:29:02 1998
+++ linux/include/linux/dcache.h Fri Jan 15 15:27:04 1999
@@ -150,10 +150,18 @@
X extern int is_root_busy(struct dentry *);
X
X /*
+ * This adds the entry to the hash queues.
+ */
+extern void d_rehash(struct dentry * entry);
+/*
X * This adds the entry to the hash queues and initializes "d_inode".
X * The entry was actually filled in earlier during "d_alloc()"
X */
-extern void d_add(struct dentry * entry, struct inode * inode);
+static __inline__ void d_add(struct dentry * entry, struct inode * inode)
+{
+ d_rehash(entry);
+ d_instantiate(entry, inode);
+}
X
X /* used for rename() and baskets */
X extern void d_move(struct dentry * entry, struct dentry * newdentry);
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.2.0-pre7/linux/include/linux/fs.h Mon Jan 4 15:08:18 1999
+++ linux/include/linux/fs.h Mon Jan 18 17:35:39 1999
@@ -208,8 +208,6 @@
X unsigned int b_list; /* List that this buffer appears */
X unsigned long b_flushtime; /* Time when this (dirty) buffer
X * should be written */
- unsigned long b_lru_time; /* Time when this buffer was
- * last used. */
X struct wait_queue * b_wait;
X struct buffer_head ** b_pprev; /* doubly linked list of hash-queue */
X struct buffer_head * b_prev_free; /* doubly linked list of buffers */
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/hdreg.h linux/include/linux/hdreg.h
--- v2.2.0-pre7/linux/include/linux/hdreg.h Thu Dec 31 10:29:02 1998
+++ linux/include/linux/hdreg.h Mon Jan 18 17:33:46 1999
@@ -141,6 +141,7 @@
X #define HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */
X #define HDIO_SCAN_HWIF 0x0328 /* register and (re)scan interface */
X #define HDIO_SET_NICE 0x0329 /* set nice flags */
+#define HDIO_UNREGISTER_HWIF 0x032a /* unregister interface */
X
X /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
X struct hd_driveid {
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/i2c.h linux/include/linux/i2c.h
--- v2.2.0-pre7/linux/include/linux/i2c.h Fri Jan 1 12:58:21 1999
+++ linux/include/linux/i2c.h Fri Jan 15 14:36:21 1999
@@ -6,7 +6,7 @@
X * There are:
X *
X * i2c the basic control module (like scsi_mod)
- * bus driver a driver with a i2c bus (host adapter driver)
+ * bus driver a driver with a i2c bus (hostadapter driver)
X * chip driver a driver for a chip connected
X * to a i2c bus (cdrom/hd driver)
X *
@@ -87,8 +87,21 @@
X
X /* needed: unsigned long flags */
X
-#define LOCK_I2C_BUS(bus) spin_lock_irqsave(&(bus->bus_lock),flags);
-#define UNLOCK_I2C_BUS(bus) spin_unlock_irqrestore(&(bus->bus_lock),flags);
+#if LINUX_VERSION_CODE >= 0x020100
+# if 0
+# define LOCK_FLAGS unsigned long flags;
+# define LOCK_I2C_BUS(bus) spin_lock_irqsave(&(bus->bus_lock),flags);
+# define UNLOCK_I2C_BUS(bus) spin_unlock_irqrestore(&(bus->bus_lock),flags);
+# else
+# define LOCK_FLAGS
+# define LOCK_I2C_BUS(bus) spin_lock(&(bus->bus_lock));
+# define UNLOCK_I2C_BUS(bus) spin_unlock(&(bus->bus_lock));
+# endif
+#else
+# define LOCK_FLAGS unsigned long flags;
+# define LOCK_I2C_BUS(bus) { save_flags(flags); cli(); }
+# define UNLOCK_I2C_BUS(bus) { restore_flags(flags); }
+#endif
X
X struct i2c_bus
X {
@@ -96,7 +109,9 @@
X int id;
X void *data; /* free for use by the bus driver */


X
+#if LINUX_VERSION_CODE >= 0x020100

X spinlock_t bus_lock;
+#endif
X
X /* attach/detach inform callbacks */
X void (*attach_inform)(struct i2c_bus *bus, int id);
@@ -163,5 +178,5 @@
X int i2c_write(struct i2c_bus *bus, unsigned char addr,
X unsigned char b1, unsigned char b2, int both);
X
-int i2c_init(void);
+int i2c_init(void);
X #endif /* I2C_H */
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/if_pppvar.h linux/include/linux/if_pppvar.h
--- v2.2.0-pre7/linux/include/linux/if_pppvar.h Fri Oct 9 13:27:16 1998
+++ linux/include/linux/if_pppvar.h Thu Jan 14 22:56:06 1999
@@ -42,7 +42,7 @@


X */
X
X /*

- * ==FILEVERSION 981004==
+ * ==FILEVERSION 990114==
X *
X * NOTE TO MAINTAINERS:

X * If you modify this file at all, please set the above date.
@@ -61,7 +61,8 @@
X #define NP_IP 0 /* Internet Protocol */
X #define NP_IPX 1 /* IPX protocol */
X #define NP_AT 2 /* Appletalk protocol */
-#define NUM_NP 3 /* Number of NPs. */
+#define NP_IPV6 3 /* Internet Protocol */
+#define NUM_NP 4 /* Number of NPs. */
X
X #define OBUFSIZE 256 /* # chars of output buffering */
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/kmod.h linux/include/linux/kmod.h
--- v2.2.0-pre7/linux/include/linux/kmod.h Tue Mar 17 22:18:15 1998
+++ linux/include/linux/kmod.h Mon Jan 18 17:33:48 1999
@@ -1,4 +1,12 @@
X /*
X kmod header
X */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_KMOD
X extern int request_module(const char * name);
+#else
+#define request_module(x) do {} while(0)
+#endif
+
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.2.0-pre7/linux/include/linux/mm.h Wed Jan 13 15:00:44 1999
+++ linux/include/linux/mm.h Mon Jan 18 17:35:41 1999
@@ -35,10 +35,17 @@
X struct mm_struct * vm_mm; /* VM area parameters */
X unsigned long vm_start;
X unsigned long vm_end;
+
+ /* linked list of VM areas per task, sorted by address */
+ struct vm_area_struct *vm_next;
+
X pgprot_t vm_page_prot;
X unsigned short vm_flags;
- struct vm_area_struct *vm_next;
- struct vm_area_struct **vm_pprev;
+
+ /* AVL tree of VM areas per task, sorted by address */
+ short vm_avl_height;
+ struct vm_area_struct * vm_avl_left;
+ struct vm_area_struct * vm_avl_right;
X
X /* For areas with inode, the list inode->i_mmap, for shm areas,
X * the list of attaches, otherwise unused.
@@ -98,7 +105,7 @@
X unsigned long (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access);
X unsigned long (*wppage)(struct vm_area_struct * area, unsigned long address,
X unsigned long page);
- int (*swapout)(struct vm_area_struct *, unsigned long, pte_t *);
+ int (*swapout)(struct vm_area_struct *, struct page *);
X pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long);
X };
X
@@ -268,7 +275,7 @@
X unsigned long address);
X
X extern void free_page_tables(struct mm_struct * mm);
-extern void clear_page_tables(struct task_struct * tsk);
+extern void clear_page_tables(struct mm_struct *, unsigned long, int);
X extern int new_page_tables(struct task_struct * tsk);
X
X extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size);
@@ -293,6 +300,7 @@
X extern void vma_init(void);
X extern void merge_segments(struct mm_struct *, unsigned long, unsigned long);
X extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
+extern void build_mmap_avl(struct mm_struct *);
X extern void exit_mmap(struct mm_struct *);
X extern unsigned long get_unmapped_area(unsigned long, unsigned long);
X
@@ -316,6 +324,7 @@
X #define __GFP_MED 0x04
X #define __GFP_HIGH 0x08
X #define __GFP_IO 0x10
+#define __GFP_SWAP 0x20
X
X #define __GFP_DMA 0x80
X
@@ -324,7 +333,7 @@
X #define GFP_USER (__GFP_LOW | __GFP_WAIT | __GFP_IO)
X #define GFP_KERNEL (__GFP_MED | __GFP_WAIT | __GFP_IO)
X #define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
-#define GFP_KSWAPD (__GFP_IO)
+#define GFP_KSWAPD (__GFP_IO | __GFP_SWAP)
X
X /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
X platforms, used as appropriate on others */
@@ -358,22 +367,7 @@
X }
X
X /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
-static inline struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
-{
- struct vm_area_struct *vma = NULL;
-
- if (mm) {
- /* Check the cache first. */
- vma = mm->mmap_cache;
- if(!vma || (vma->vm_end <= addr) || (vma->vm_start > addr)) {
- vma = mm->mmap;
- while(vma && vma->vm_end <= addr)
- vma = vma->vm_next;
- mm->mmap_cache = vma;
- }
- }
- return vma;
-}
+extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);
X
X /* Look up the first VMA which intersects the interval start_addr..end_addr-1,
X NULL if none. Assume start_addr < end_addr. */
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.2.0-pre7/linux/include/linux/pci.h Thu Jan 7 15:11:40 1999
+++ linux/include/linux/pci.h Mon Jan 18 17:33:46 1999
@@ -592,6 +592,8 @@
X #define PCI_VENDOR_ID_BROOKTREE 0x109e
X #define PCI_DEVICE_ID_BROOKTREE_848 0x0350
X #define PCI_DEVICE_ID_BROOKTREE_849A 0x0351
+#define PCI_DEVICE_ID_BROOKTREE_878_1 0x036e
+#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
X #define PCI_DEVICE_ID_BROOKTREE_8474 0x8474
X
X #define PCI_VENDOR_ID_SIERRA 0x10a8
@@ -904,6 +906,7 @@
X #define PCI_VENDOR_ID_3DFX 0x121a
X #define PCI_DEVICE_ID_3DFX_VOODOO 0x0001
X #define PCI_DEVICE_ID_3DFX_VOODOO2 0x0002
+#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003
X
X #define PCI_VENDOR_ID_SIGMADES 0x1236
X #define PCI_DEVICE_ID_SIGMADES_6425 0x6401
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/poll.h linux/include/linux/poll.h
--- v2.2.0-pre7/linux/include/linux/poll.h Sun Nov 8 14:03:11 1998
+++ linux/include/linux/poll.h Mon Jan 18 17:35:44 1999
@@ -7,6 +7,7 @@
X
X #include <linux/wait.h>
X #include <linux/string.h>
+#include <linux/mm.h>
X #include <asm/uaccess.h>
X
X
@@ -17,11 +18,12 @@
X };
X
X typedef struct poll_table_struct {
+ struct poll_table_struct * next;
X unsigned int nr;
X struct poll_table_entry * entry;
X } poll_table;
X
-#define __MAX_POLL_TABLE_ENTRIES (PAGE_SIZE / sizeof (struct poll_table_entry))
+#define __MAX_POLL_TABLE_ENTRIES ((PAGE_SIZE - sizeof (poll_table)) / sizeof (struct poll_table_entry))
X
X extern inline void poll_wait(struct file * filp, struct wait_queue ** wait_address, poll_table *p)
X {
@@ -29,8 +31,18 @@
X
X if (!p || !wait_address)
X return;
- if (p->nr >= __MAX_POLL_TABLE_ENTRIES)
- return;
+ while (p->nr >= __MAX_POLL_TABLE_ENTRIES && p->next != NULL)
+ p = p->next;
+ if (p->nr >= __MAX_POLL_TABLE_ENTRIES) {
+ poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL);
+ if (!tmp)
+ return;
+ tmp->nr = 0;
+ tmp->entry = (struct poll_table_entry *)(tmp + 1);
+ tmp->next = NULL;
+ p->next = tmp;
+ p = tmp;
+ }
X entry = p->entry + p->nr;
X entry->filp = filp;
X filp->f_count++;
@@ -59,11 +71,30 @@
X #define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8)
X typedef unsigned long kernel_fd_set[KFDS_NR/__NFDBITS];
X
+/*
+ * XXX - still used by alpha osf and sparc32 compatiblity.
+ */
+
X typedef struct {
X kernel_fd_set in, out, ex;
X kernel_fd_set res_in, res_out, res_ex;
X } fd_set_buffer;
X
+/*
+ * Scaleable version of the fd_set.
+ */
+
+typedef struct {
+ unsigned long *in, *out, *ex;
+ unsigned long *res_in, *res_out, *res_ex;
+} fd_set_bits;
+
+/*
+ * How many longwords for "nr" bits?
+ */
+#define FDS_BITPERLONG (8*sizeof(long))
+#define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)
+#define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long))
X
X /*
X * We do a VERIFY_WRITE here even though we are only reading this time:
@@ -74,8 +105,7 @@
X static inline
X int get_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
X {
- /* round up nr to nearest "unsigned long" */
- nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long)) * sizeof(long);
+ nr = FDS_BYTES(nr);
X if (ufdset) {
X int error;
X error = verify_area(VERIFY_WRITE, ufdset, nr);
@@ -90,20 +120,17 @@
X static inline
X void set_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
X {
- if (ufdset) {
- nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long))*sizeof(long);
- __copy_to_user(ufdset, fdset, nr);
- }
+ if (ufdset)
+ __copy_to_user(ufdset, fdset, FDS_BYTES(nr));
X }
X
X static inline
X void zero_fd_set(unsigned long nr, unsigned long *fdset)
X {
- nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long)) * sizeof(long);
- memset(fdset, 0, nr);
+ memset(fdset, 0, FDS_BYTES(nr));
X }
X
-extern int do_select(int n, fd_set_buffer *fds, long *timeout);
+extern int do_select(int n, fd_set_bits *fds, long *timeout);
X
X #endif /* KERNEL */
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/ppp_defs.h linux/include/linux/ppp_defs.h
--- v2.2.0-pre7/linux/include/linux/ppp_defs.h Sat Nov 29 10:33:21 1997
+++ linux/include/linux/ppp_defs.h Thu Jan 14 22:56:06 1999
@@ -28,7 +28,7 @@


X */
X
X /*

- * ==FILEVERSION 970607==


+ * ==FILEVERSION 990114==
X *
X * NOTE TO MAINTAINERS:

X * If you modify this file at all, please set the above date.
@@ -75,6 +75,7 @@
X #define PPP_IPCP 0x8021 /* IP Control Protocol */
X #define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
X #define PPP_IPXCP 0x802b /* IPX Control Protocol */
+#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
X #define PPP_CCP 0x80fd /* Compression Control Protocol */
X #define PPP_LCP 0xc021 /* Link Control Protocol */
X #define PPP_PAP 0xc023 /* Password Authentication Protocol */
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/quota.h linux/include/linux/quota.h
--- v2.2.0-pre7/linux/include/linux/quota.h Mon Sep 28 10:51:35 1998
+++ linux/include/linux/quota.h Thu Jan 14 22:56:06 1999
@@ -86,7 +86,7 @@
X extern int dquot_root_squash;
X
X #define NR_DQHASH 43 /* Just an arbitrary number */
-#define NR_DQUOTS 256 /* Maximum number of quotas active at one time (Configurable from /proc/sys/fs) */
+#define NR_DQUOTS 1024 /* Maximum number of quotas active at one time (Configurable from /proc/sys/fs) */
X
X /*
X * Command definitions for the 'quotactl' system call.
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.2.0-pre7/linux/include/linux/sched.h Wed Jan 13 15:00:44 1999
+++ linux/include/linux/sched.h Mon Jan 18 17:35:41 1999
@@ -33,7 +33,7 @@
X #define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */
X #define CLONE_PID 0x00001000 /* set if pid shared */
X #define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
-#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mmput */
+#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
X
X /*
X * These are the constant used to fake the fixed-point load-average
@@ -156,11 +156,16 @@
X /* Maximum number of active map areas.. This is a random (large) number */
X #define MAX_MAP_COUNT (65536)
X
+/* Number of map areas at which the AVL tree is activated. This is arbitrary. */
+#define AVL_MIN_MAP_COUNT 32
+
X struct mm_struct {
- struct vm_area_struct *mmap, *mmap_cache;
+ struct vm_area_struct *mmap; /* list of VMAs */
+ struct vm_area_struct *mmap_avl; /* tree of VMAs */
+ struct vm_area_struct *mmap_cache; /* last find_vma result */
X pgd_t * pgd;
X atomic_t count;
- int map_count;
+ int map_count; /* number of VMAs */
X struct semaphore mmap_sem;
X unsigned long context;
X unsigned long start_code, end_code, start_data, end_data;
@@ -177,7 +182,8 @@
X };
X
X #define INIT_MM { \
- &init_mmap, NULL, swapper_pg_dir, \
+ &init_mmap, NULL, NULL, \
+ swapper_pg_dir, \
X ATOMIC_INIT(1), 1, \
X MUTEX, \
X 0, \
@@ -321,7 +327,7 @@
X #define PF_DUMPCORE 0x00000200 /* dumped core */
X #define PF_SIGNALED 0x00000400 /* killed by a signal */
X #define PF_MEMALLOC 0x00000800 /* Allocating memory */
-#define PF_VFORK 0x00001000 /* Wake up parent in mmput */
+#define PF_VFORK 0x00001000 /* Wake up parent in mm_release */
X
X #define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */
X #define PF_DTRACE 0x00200000 /* delayed trace (used on m68k, i386) */
@@ -332,7 +338,7 @@
X */
X #define _STK_LIM (8*1024*1024)
X
-#define DEF_PRIORITY (20*HZ/100) /* 200 ms time slices */
+#define DEF_PRIORITY (20*HZ/100) /* 210 ms time slices */
X
X /*
X * INIT_TASK is used to set up the first task table, touch at
@@ -608,6 +614,8 @@
X atomic_inc(&mm->count);
X }
X extern void mmput(struct mm_struct *);
+/* Remove the current tasks stale references to the old mm_struct */
+extern void mm_release(void);
X
X extern int copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
X extern void flush_thread(void);
diff -u --recursive --new-file v2.2.0-pre7/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.2.0-pre7/linux/include/linux/videodev.h Mon Dec 28 15:00:53 1998
+++ linux/include/linux/videodev.h Thu Jan 14 22:53:12 1999
@@ -1,9 +1,13 @@
X #ifndef __LINUX_VIDEODEV_H
X #define __LINUX_VIDEODEV_H
X
+#include <linux/types.h>
+
X #ifdef __KERNEL__


X
+#if LINUX_VERSION_CODE >= 0x020100

X #include <linux/poll.h>
+#endif
X
X struct video_device
X {
@@ -16,7 +20,9 @@
X long (*read)(struct video_device *, char *, unsigned long, int noblock);
X /* Do we need a write method ? */
X long (*write)(struct video_device *, const char *, unsigned long, int noblock);
+#if LINUX_VERSION_CODE >= 0x020100
X unsigned int (*poll)(struct video_device *, struct file *, poll_table *);
+#endif
X int (*ioctl)(struct video_device *, unsigned int , void *);
X int (*mmap)(struct video_device *, const char *, unsigned long);
X int (*initialize)(struct video_device *);
@@ -48,7 +54,6 @@
X #define VID_TYPE_SCALES 128 /* Scalable */
X #define VID_TYPE_MONOCHROME 256 /* Monochrome only */
X #define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */
-#define VID_TYPE_OUTPUT 1024 /* Can output video data */
X
X struct video_capability
X {
@@ -120,6 +125,10 @@
X #define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
X #define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
X #define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
+#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */
+#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */
+#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */
+#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */
X };
X
X struct video_audio
@@ -138,7 +147,7 @@
X #define VIDEO_SOUND_STEREO 2
X #define VIDEO_SOUND_LANG1 4
X #define VIDEO_SOUND_LANG2 8
- __u16 mode; /* detected audio carriers or one to set */
+ __u16 mode;
X __u16 balance; /* Stereo balance */
X __u16 step; /* Step actual volume uses */
X };
diff -u --recursive --new-file v2.2.0-pre7/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.2.0-pre7/linux/include/net/tcp.h Sun Nov 8 14:03:12 1998
+++ linux/include/net/tcp.h Mon Jan 18 17:35:45 1999
@@ -813,8 +813,9 @@
X /* This tells the input processing path that an ACK should go out
X * right now.
X */
-#define tcp_enter_quickack_mode(__tp) ((__tp)->ato = (HZ/100))
-#define tcp_in_quickack_mode(__tp) ((__tp)->ato == (HZ/100))
+#define tcp_enter_quickack_mode(__tp) ((__tp)->ato |= (1<<31))
+#define tcp_exit_quickack_mode(__tp) ((__tp)->ato &= ~(1<<31))
+#define tcp_in_quickack_mode(__tp) (((__tp)->ato & (1 << 31)) != 0)
X
X /*
X * List all states of a TCP socket that can be viewed as a "connected"
diff -u --recursive --new-file v2.2.0-pre7/linux/kernel/exit.c linux/kernel/exit.c
--- v2.2.0-pre7/linux/kernel/exit.c Fri Jan 8 22:36:25 1999
+++ linux/kernel/exit.c Mon Jan 18 09:55:31 1999
@@ -258,6 +258,7 @@
X tsk->mm = &init_mm;
X tsk->swappable = 0;
X SET_PAGE_DIR(tsk, swapper_pg_dir);
+ mm_release();
X mmput(mm);
X }
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/kernel/fork.c linux/kernel/fork.c
--- v2.2.0-pre7/linux/kernel/fork.c Wed Jan 13 15:00:44 1999
+++ linux/kernel/fork.c Mon Jan 18 09:55:50 1999
@@ -16,6 +16,7 @@
X #include <linux/unistd.h>
X #include <linux/smp_lock.h>
X #include <linux/module.h>
+#include <linux/vmalloc.h>
X
X #include <asm/pgtable.h>
X #include <asm/mmu_context.h>
@@ -230,16 +231,16 @@
X * Link in the new vma even if an error occurred,
X * so that exit_mmap() can clean up the mess.
X */
- if((tmp->vm_next = *pprev) != NULL)
- (*pprev)->vm_pprev = &tmp->vm_next;
+ tmp->vm_next = *pprev;
X *pprev = tmp;
- tmp->vm_pprev = pprev;
X
X pprev = &tmp->vm_next;
X if (retval)
X goto fail_nomem;
X }
X retval = 0;
+ if (mm->map_count >= AVL_MIN_MAP_COUNT)
+ build_mmap_avl(mm);
X
X fail_nomem:
X flush_tlb_mm(current->mm);
@@ -268,7 +269,7 @@
X * Leave mm->pgd set to the parent's pgd
X * so that pgd_offset() is always valid.
X */
- mm->mmap = mm->mmap_cache = NULL;
+ mm->mmap = mm->mmap_avl = mm->mmap_cache = NULL;
X
X /* It has not run yet, so cannot be present in anyone's
X * cache or tlb.
@@ -278,17 +279,35 @@
X return mm;
X }
X
-/*
- * Decrement the use count and release all resources for an mm.
+/* Please note the differences between mmput and mm_release.
+ * mmput is called whenever we stop holding onto a mm_struct,
+ * error success whatever.
+ *
+ * mm_release is called after a mm_struct has been removed
+ * from the current process.
+ *
+ * This difference is important for error handling, when we
+ * only half set up a mm_struct for a new process and need to restore
+ * the old one. Because we mmput the new mm_struct before
+ * restoring the old one. . .
+ * Eric Biederman 10 January 1998
X */
-void mmput(struct mm_struct *mm)
+void mm_release(void)
X {
+ struct task_struct *tsk = current;
+ forget_segments();
X /* notify parent sleeping on vfork() */
- if (current->flags & PF_VFORK) {
- current->flags &= ~PF_VFORK;
- up(current->p_opptr->vfork_sem);
+ if (tsk->flags & PF_VFORK) {
+ tsk->flags &= ~PF_VFORK;
+ up(tsk->p_opptr->vfork_sem);
X }
+}
X
+/*
+ * Decrement the use count and release all resources for an mm.
+ */
+void mmput(struct mm_struct *mm)
+{
X if (atomic_dec_and_test(&mm->count)) {
X release_segments(mm);
X exit_mmap(mm);
@@ -478,6 +497,9 @@
X int nr;
X int retval = -ENOMEM;
X struct task_struct *p;
+ struct semaphore sem = MUTEX_LOCKED;
+
+ current->vfork_sem = &sem;
X
X p = alloc_task_struct();
X if (!p)
@@ -611,9 +633,11 @@
X }
X ++total_forks;
X bad_fork:
- up(&current->mm->mmap_sem);
X unlock_kernel();
+ up(&current->mm->mmap_sem);
X fork_out:
+ if ((clone_flags & CLONE_VFORK) && (retval > 0))
+ down(&sem);
X return retval;
X
X bad_fork_cleanup_sighand:
diff -u --recursive --new-file v2.2.0-pre7/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.2.0-pre7/linux/kernel/ksyms.c Thu Jan 7 15:11:41 1999
+++ linux/kernel/ksyms.c Fri Jan 15 11:28:03 1999
@@ -121,7 +121,8 @@
X EXPORT_SYMBOL(d_alloc_root);
X EXPORT_SYMBOL(d_delete);
X EXPORT_SYMBOL(d_validate);
-EXPORT_SYMBOL(d_add);
+EXPORT_SYMBOL(d_rehash);
+EXPORT_SYMBOL(d_invalidate); /* May be it will be better in dcache.h? */
X EXPORT_SYMBOL(d_move);
X EXPORT_SYMBOL(d_instantiate);
X EXPORT_SYMBOL(d_alloc);
diff -u --recursive --new-file v2.2.0-pre7/linux/kernel/sched.c linux/kernel/sched.c
--- v2.2.0-pre7/linux/kernel/sched.c Thu Jan 7 15:11:41 1999
+++ linux/kernel/sched.c Fri Jan 15 11:33:27 1999
@@ -883,7 +883,7 @@
X * who gets to gate through and who has to wait some more. \
X */ \
X for (;;) { \
- if (waking_non_zero(sem)) /* are we waking up? */ \
+ if (waking_non_zero(sem, tsk)) /* are we waking up? */ \
X break; /* yes, exit loop */
X
X #define DOWN_TAIL(task_state) \
@@ -1551,7 +1551,7 @@
X * do a "normalization" of the priority (traditionally
X * Unix nice values are -20 to 20; Linux doesn't really
X * use that kind of thing, but uses the length of the
- * timeslice instead (default 150 ms). The rounding is
+ * timeslice instead (default 210 ms). The rounding is
X * why we want to avoid negative values.
X */
X newprio = (newprio * DEF_PRIORITY + 10) / 20;
diff -u --recursive --new-file v2.2.0-pre7/linux/mm/filemap.c linux/mm/filemap.c
--- v2.2.0-pre7/linux/mm/filemap.c Thu Jan 7 15:11:41 1999
+++ linux/mm/filemap.c Thu Jan 14 11:39:54 1999
@@ -1085,22 +1085,6 @@
X struct file * file;
X struct dentry * dentry;
X struct inode * inode;
- struct buffer_head * bh;
-
- bh = mem_map[MAP_NR(page)].buffers;
- if (bh) {
- /* whee.. just mark the buffer heads dirty */
- struct buffer_head * tmp = bh;
- do {
- /*
- * WSH: There's a race here: mark_buffer_dirty()
- * could block, and the buffers aren't pinned down.
- */
- mark_buffer_dirty(tmp, 0);
- tmp = tmp->b_this_page;
- } while (tmp != bh);
- return 0;
- }
X
X file = vma->vm_file;
X dentry = file->f_dentry;
@@ -1122,50 +1106,15 @@
X
X
X /*
- * Swapping to a shared file: while we're busy writing out the page
- * (and the page still exists in memory), we save the page information
- * in the page table, so that "filemap_swapin()" can re-use the page
- * immediately if it is called while we're busy swapping it out..
- *
- * Once we've written it all out, we mark the page entry "empty", which
- * will result in a normal page-in (instead of a swap-in) from the now
- * up-to-date disk file.
+ * The page cache takes care of races between somebody
+ * trying to swap something out and swap something in
+ * at the same time..
X */
-int filemap_swapout(struct vm_area_struct * vma,
- unsigned long offset,
- pte_t *page_table)
+int filemap_swapout(struct vm_area_struct * vma, struct page * page)
X {
- int error;
- unsigned long page = pte_page(*page_table);
- unsigned long entry = SWP_ENTRY(SHM_SWP_TYPE, MAP_NR(page));
-
- flush_cache_page(vma, (offset + vma->vm_start - vma->vm_offset));
- set_pte(page_table, __pte(entry));
- flush_tlb_page(vma, (offset + vma->vm_start - vma->vm_offset));
- error = filemap_write_page(vma, offset, page);
- if (pte_val(*page_table) == entry)
- pte_clear(page_table);
- return error;
+ return filemap_write_page(vma, page->offset, page_address(page));
X }
X
-/*
- * filemap_swapin() is called only if we have something in the page
- * tables that is non-zero (but not present), which we know to be the
- * page index of a page that is busy being swapped out (see above).
- * So we just use it directly..
- */
-static pte_t filemap_swapin(struct vm_area_struct * vma,
- unsigned long offset,
- unsigned long entry)
-{
- unsigned long page = SWP_OFFSET(entry);
-
- atomic_inc(&mem_map[page].count);
- page = (page << PAGE_SHIFT) + PAGE_OFFSET;
- return mk_pte(page,vma->vm_page_prot);
-}
-
-
X static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
X unsigned long address, unsigned int flags)
X {
@@ -1306,7 +1255,7 @@
X filemap_nopage, /* nopage */
X NULL, /* wppage */
X filemap_swapout, /* swapout */
- filemap_swapin, /* swapin */
+ NULL, /* swapin */
X };
X
X /*
diff -u --recursive --new-file v2.2.0-pre7/linux/mm/memory.c linux/mm/memory.c
--- v2.2.0-pre7/linux/mm/memory.c Thu Jan 7 15:11:41 1999
+++ linux/mm/memory.c Mon Jan 18 17:33:10 1999
@@ -126,48 +126,36 @@
X * This function clears all user-level page tables of a process - this
X * is needed by execve(), so that old pages aren't in the way.
X */
-void clear_page_tables(struct task_struct * tsk)
+void clear_page_tables(struct mm_struct *mm, unsigned long first, int nr)
X {
- pgd_t * page_dir = tsk->mm->pgd;
- int i;
-
- if (!page_dir || page_dir == swapper_pg_dir)
- goto out_bad;
- for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
- free_one_pgd(page_dir + i);
-
- /* keep the page table cache within bounds */
- check_pgt_cache();
- return;
+ pgd_t * page_dir = mm->pgd;
X
-out_bad:
- printk(KERN_ERR
- "clear_page_tables: %s trying to clear kernel pgd\n",
- tsk->comm);
- return;
+ if (page_dir && page_dir != swapper_pg_dir) {
+ page_dir += first;
+ do {
+ free_one_pgd(page_dir);
+ page_dir++;
+ } while (--nr);
+
+ /* keep the page table cache within bounds */
+ check_pgt_cache();


+ }
X }
X
X /*

- * This function frees up all page tables of a process when it exits. It
- * is the same as "clear_page_tables()", except it also frees the old
- * page table directory.
+ * This function just free's the page directory - the
+ * pages tables themselves have been freed earlier by
+ * clear_page_tables().
X */
X void free_page_tables(struct mm_struct * mm)
X {
X pgd_t * page_dir = mm->pgd;
- int i;
X
- if (!page_dir)
- goto out;
- if (page_dir == swapper_pg_dir)
- goto out_bad;
- for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
- free_one_pgd(page_dir + i);
- pgd_free(page_dir);
-
- /* keep the page table cache within bounds */
- check_pgt_cache();
-out:
+ if (page_dir) {
+ if (page_dir == swapper_pg_dir)
+ goto out_bad;
+ pgd_free(page_dir);
+ }
X return;
X
X out_bad:
@@ -204,7 +192,7 @@
X pgd_t * src_pgd, * dst_pgd;
X unsigned long address = vma->vm_start;
X unsigned long end = vma->vm_end;
- unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE;
+ unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
X
X src_pgd = pgd_offset(src, address)-1;
X dst_pgd = pgd_offset(dst, address)-1;
@@ -277,10 +265,15 @@
X set_pte(dst_pte, pte);
X goto cont_copy_pte_range;
X }
- if (cow)
+ /* If it's a COW mapping, write protect it both in the parent and the child */
+ if (cow) {
X pte = pte_wrprotect(pte);
+ set_pte(src_pte, pte);
+ }
+ /* If it's a shared mapping, mark it clean in the child */
+ if (vma->vm_flags & VM_SHARED)
+ pte = pte_mkclean(pte);
X set_pte(dst_pte, pte_mkold(pte));
- set_pte(src_pte, pte);
X atomic_inc(&mem_map[page_nr].count);
X
X cont_copy_pte_range: address += PAGE_SIZE;
diff -u --recursive --new-file v2.2.0-pre7/linux/mm/mmap.c linux/mm/mmap.c
--- v2.2.0-pre7/linux/mm/mmap.c Fri Nov 27 13:09:30 1998
+++ linux/mm/mmap.c Mon Jan 18 16:24:06 1999
@@ -371,6 +371,99 @@
X }
X }
X
+#define vm_avl_empty (struct vm_area_struct *) NULL
+
+#include "mmap_avl.c"
+
+/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
+struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
+{
+ struct vm_area_struct *vma = NULL;
+
+ if (mm) {
+ /* Check the cache first. */
+ /* (Cache hit rate is typically around 35%.) */
+ vma = mm->mmap_cache;
+ if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {
+ if (!mm->mmap_avl) {
+ /* Go through the linear list. */
+ vma = mm->mmap;
+ while (vma && vma->vm_end <= addr)
+ vma = vma->vm_next;
+ } else {
+ /* Then go through the AVL tree quickly. */
+ struct vm_area_struct * tree = mm->mmap_avl;
+ for (;;) {
+ if (tree == vm_avl_empty)
+ break;
+ if (tree->vm_end > addr) {
+ vma = tree;
+ if (tree->vm_start <= addr)
+ break;
+ tree = tree->vm_avl_left;
+ } else
+ tree = tree->vm_avl_right;
+ }
+ }
+ if (vma)
+ mm->mmap_cache = vma;
+ }
+ }
+ return vma;
+}
+
+/* Same as find_vma, but also return a pointer to the previous VMA in *pprev. */
+struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
+ struct vm_area_struct **pprev)
+{
+ if (mm) {
+ if (!mm->mmap_avl) {
+ /* Go through the linear list. */
+ struct vm_area_struct * prev = NULL;
+ struct vm_area_struct * vma = mm->mmap;
+ while (vma && vma->vm_end <= addr) {
+ prev = vma;
+ vma = vma->vm_next;
+ }
+ *pprev = prev;
+ return vma;
+ } else {
+ /* Go through the AVL tree quickly. */
+ struct vm_area_struct * vma = NULL;
+ struct vm_area_struct * last_turn_right = NULL;
+ struct vm_area_struct * prev = NULL;
+ struct vm_area_struct * tree = mm->mmap_avl;
+ for (;;) {
+ if (tree == vm_avl_empty)
+ break;
+ if (tree->vm_end > addr) {
+ vma = tree;
+ prev = last_turn_right;
+ if (tree->vm_start <= addr)
+ break;
+ tree = tree->vm_avl_left;
+ } else {
+ last_turn_right = tree;
+ tree = tree->vm_avl_right;
+ }
+ }
+ if (vma) {
+ if (vma->vm_avl_left != vm_avl_empty) {
+ prev = vma->vm_avl_left;
+ while (prev->vm_avl_right != vm_avl_empty)
+ prev = prev->vm_avl_right;
+ }
+ if ((prev ? prev->vm_next : mm->mmap) != vma)
+ printk("find_vma_prev: tree inconsistent with list\n");
+ *pprev = prev;
+ return vma;
+ }
+ }
+ }
+ *pprev = NULL;
+ return NULL;
+}
+
X /* Normal function to fix up a mapping
X * This function is the default for when an area has no specific
X * function. This may be used as part of a more specific routine.
@@ -446,6 +539,57 @@


X return 1;
X }
X

+/*
+ * Try to free as many page directory entries as we can,
+ * without having to work very hard at actually scanning
+ * the page tables themselves.
+ *
+ * Right now we try to free page tables if we have a nice
+ * PGDIR-aligned area that got free'd up. We could be more
+ * granular if we want to, but this is fast and simple,
+ * and covers the bad cases.
+ *
+ * "prev", if it exists, points to a vma before the one
+ * we just free'd - but there's no telling how much before.
+ */
+static void free_pgtables(struct mm_struct * mm, struct vm_area_struct *prev,
+ unsigned long start, unsigned long end)
+{
+ unsigned long first = start & PGDIR_MASK;
+ unsigned long last = (end & PGDIR_MASK) + PGDIR_SIZE;
+
+ if (!prev) {
+ prev = mm->mmap;
+ if (!prev)
+ goto no_mmaps;
+ if (prev->vm_end > start) {
+ if (last > prev->vm_end)
+ last = prev->vm_end;
+ goto no_mmaps;
+ }
+ }
+ for (;;) {
+ struct vm_area_struct *next = prev->vm_next;
+
+ if (next) {
+ if (next->vm_start < start) {
+ prev = next;
+ continue;
+ }
+ if (last > next->vm_start)
+ last = next->vm_start;
+ }
+ if (prev->vm_end > first)
+ first = prev->vm_end + PGDIR_SIZE - 1;
+ break;
+ }
+no_mmaps:
+ first = first >> PGDIR_SHIFT;
+ last = last >> PGDIR_SHIFT;
+ if (last > first)
+ clear_page_tables(mm, first, last-first);
+}
+
X /* Munmap is split into 2 main parts -- this part which finds
X * what needs doing, and the areas themselves, which do the
X * work. This now handles partial unmappings.
@@ -454,8 +598,7 @@
X int do_munmap(unsigned long addr, size_t len)
X {
X struct mm_struct * mm;
- struct vm_area_struct *mpnt, *free, *extra;
- int freed;
+ struct vm_area_struct *mpnt, *prev, **npp, *free, *extra;
X
X if ((addr & ~PAGE_MASK) || addr > TASK_SIZE || len > TASK_SIZE-addr)
X return -EINVAL;
@@ -469,15 +612,17 @@
X * on the list. If nothing is put on, nothing is affected.
X */
X mm = current->mm;
- mpnt = mm->mmap;
- while(mpnt && mpnt->vm_end <= addr)
- mpnt = mpnt->vm_next;
+ mpnt = find_vma_prev(mm, addr, &prev);
X if (!mpnt)
X return 0;
+ /* we have addr < mpnt->vm_end */
+
+ if (mpnt->vm_start >= addr+len)
+ return 0;
X
X /* If we'll make "hole", check the vm areas limit */
- if ((mpnt->vm_start < addr && mpnt->vm_end > addr+len) &&
- mm->map_count > MAX_MAP_COUNT)
+ if ((mpnt->vm_start < addr && mpnt->vm_end > addr+len)
+ && mm->map_count >= MAX_MAP_COUNT)
X return -ENOMEM;
X
X /*
@@ -488,18 +633,14 @@
X if (!extra)
X return -ENOMEM;
X
- /* we have addr < mpnt->vm_end */
+ npp = (prev ? &prev->vm_next : &mm->mmap);
X free = NULL;
- for ( ; mpnt && mpnt->vm_start < addr+len; ) {
- struct vm_area_struct *next = mpnt->vm_next;
-
- if(mpnt->vm_next)
- mpnt->vm_next->vm_pprev = mpnt->vm_pprev;
- *mpnt->vm_pprev = mpnt->vm_next;
-
+ for ( ; mpnt && mpnt->vm_start < addr+len; mpnt = *npp) {
+ *npp = mpnt->vm_next;
X mpnt->vm_next = free;
X free = mpnt;
- mpnt = next;
+ if (mm->mmap_avl)
+ avl_remove(mpnt, &mm->mmap_avl);
X }
X
X /* Ok - we have the memory areas we should free on the 'free' list,
@@ -507,15 +648,10 @@
X * If the one of the segments is only being partially unmapped,
X * it will put new vm_area_struct(s) into the address space.
X */
- freed = 0;
X while ((mpnt = free) != NULL) {
X unsigned long st, end, size;
X
X free = free->vm_next;
- freed = 1;
-
- mm->map_count--;
- remove_shared_vm_struct(mpnt);
X
X st = addr < mpnt->vm_start ? mpnt->vm_start : addr;
X end = addr+len;
@@ -525,6 +661,9 @@
X if (mpnt->vm_ops && mpnt->vm_ops->unmap)
X mpnt->vm_ops->unmap(mpnt, st, size);
X
+ remove_shared_vm_struct(mpnt);
+ mm->map_count--;
+
X flush_cache_range(mm, st, end);
X zap_page_range(mm, st, size);
X flush_tlb_range(mm, st, end);
@@ -540,8 +679,9 @@
X if (extra)
X kmem_cache_free(vm_area_cachep, extra);
X
- if (freed)
- mm->mmap_cache = NULL; /* Kill the cache. */
+ free_pgtables(mm, prev, addr, addr+len);
+
+ mm->mmap_cache = NULL; /* Kill the cache. */


X return 0;
X }
X

@@ -557,13 +697,23 @@
X return ret;
X }
X
+/* Build the AVL tree corresponding to the VMA list. */
+void build_mmap_avl(struct mm_struct * mm)
+{
+ struct vm_area_struct * vma;
+
+ mm->mmap_avl = NULL;
+ for (vma = mm->mmap; vma; vma = vma->vm_next)
+ avl_insert(vma, &mm->mmap_avl);
+}
+
X /* Release all mmaps. */
X void exit_mmap(struct mm_struct * mm)
X {
X struct vm_area_struct * mpnt;
X
X mpnt = mm->mmap;
- mm->mmap = mm->mmap_cache = NULL;
+ mm->mmap = mm->mmap_avl = mm->mmap_cache = NULL;
X mm->rss = 0;
X mm->total_vm = 0;
X mm->locked_vm = 0;
@@ -591,6 +741,8 @@
X /* This is just debugging */
X if (mm->map_count)
X printk("exit_mmap: map count is %d\n", mm->map_count);
+
+ clear_page_tables(mm, 0, USER_PTRS_PER_PGD);
X }
X
X /* Insert vm structure into process list sorted by address
@@ -598,20 +750,26 @@
X */
X void insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vmp)
X {
- struct vm_area_struct **pprev = &mm->mmap;
+ struct vm_area_struct **pprev;
X struct file * file;
X
- mm->map_count++;
-
- /* Find where to link it in. */
- while(*pprev && (*pprev)->vm_start <= vmp->vm_start)
- pprev = &(*pprev)->vm_next;
-
- /* Insert it. */
- if((vmp->vm_next = *pprev) != NULL)
- (*pprev)->vm_pprev = &vmp->vm_next;
+ if (!mm->mmap_avl) {
+ pprev = &mm->mmap;
+ while (*pprev && (*pprev)->vm_start <= vmp->vm_start)
+ pprev = &(*pprev)->vm_next;
+ } else {
+ struct vm_area_struct *prev, *next;
+ avl_insert_neighbours(vmp, &mm->mmap_avl, &prev, &next);
+ pprev = (prev ? &prev->vm_next : &mm->mmap);
+ if (*pprev != next)
+ printk("insert_vm_struct: tree inconsistent with list\n");
+ }
+ vmp->vm_next = *pprev;
X *pprev = vmp;
- vmp->vm_pprev = pprev;
+
+ mm->map_count++;
+ if (mm->map_count >= AVL_MIN_MAP_COUNT && !mm->mmap_avl)
+ build_mmap_avl(mm);
X
X file = vmp->vm_file;
X if (file) {
@@ -637,23 +795,17 @@
X */
X void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr)
X {
- struct vm_area_struct *prev, *mpnt, *next;
+ struct vm_area_struct *prev, *mpnt, *next, *prev1;
X
- prev = NULL;
- mpnt = mm->mmap;
- while(mpnt && mpnt->vm_end <= start_addr) {
- prev = mpnt;
- mpnt = mpnt->vm_next;
- }
+ mpnt = find_vma_prev(mm, start_addr, &prev1);
X if (!mpnt)
X return;
X
- next = mpnt->vm_next;
-
- /* we have prev->vm_next == mpnt && mpnt->vm_next = next */
- if (!prev) {
+ if (prev1) {
+ prev = prev1;
+ } else {
X prev = mpnt;
- mpnt = next;
+ mpnt = mpnt->vm_next;
X }
X
X /* prev and mpnt cycle through the list, as long as
@@ -684,11 +836,10 @@
X * big segment can possibly merge with the next one.
X * The old unused mpnt is freed.
X */
- if(mpnt->vm_next)
- mpnt->vm_next->vm_pprev = mpnt->vm_pprev;
- *mpnt->vm_pprev = mpnt->vm_next;
-
+ if (mm->mmap_avl)
+ avl_remove(mpnt, &mm->mmap_avl);
X prev->vm_end = mpnt->vm_end;
+ prev->vm_next = mpnt->vm_next;
X if (mpnt->vm_ops && mpnt->vm_ops->close) {
X mpnt->vm_offset += mpnt->vm_end - mpnt->vm_start;
X mpnt->vm_start = mpnt->vm_end;
diff -u --recursive --new-file v2.2.0-pre7/linux/mm/mmap_avl.c linux/mm/mmap_avl.c
--- v2.2.0-pre7/linux/mm/mmap_avl.c Wed Dec 31 16:00:00 1969
+++ linux/mm/mmap_avl.c Fri Jan 15 14:41:04 1999
@@ -0,0 +1,374 @@
+/*
+ * Searching a VMA in the linear list task->mm->mmap is horribly slow.
+ * Use an AVL (Adelson-Velskii and Landis) tree to speed up this search
+ * from O(n) to O(log n), where n is the number of VMAs of the task
+ * n is typically around 6, but may reach 3000 in some cases: object-oriented
+ * databases, persistent store, generational garbage collection (Java, Lisp),
+ * ElectricFence.
+ * Written by Bruno Haible <hai...@ma2s2.mathematik.uni-karlsruhe.de>.
+ */
+
+/* We keep the list and tree sorted by address. */
+#define vm_avl_key vm_end
+#define vm_avl_key_t unsigned long /* typeof(vma->avl_key) */
+
+/*
+ * task->mm->mmap_avl is the AVL tree corresponding to task->mm->mmap
+ * or, more exactly, its root.
+ * A vm_area_struct has the following fields:
+ * vm_avl_left left son of a tree node
+ * vm_avl_right right son of a tree node
+ * vm_avl_height 1+max(heightof(left),heightof(right))
+ * The empty tree is represented as NULL.
+ */
+
+/* Since the trees are balanced, their height will never be large. */
+#define avl_maxheight 41 /* why this? a small exercise */
+#define heightof(tree) ((tree) == vm_avl_empty ? 0 : (tree)->vm_avl_height)
+/*
+ * Consistency and balancing rules:
+ * 1. tree->vm_avl_height == 1+max(heightof(tree->vm_avl_left),heightof(tree->vm_avl_right))
+ * 2. abs( heightof(tree->vm_avl_left) - heightof(tree->vm_avl_right) ) <= 1
+ * 3. foreach node in tree->vm_avl_left: node->vm_avl_key <= tree->vm_avl_key,
+ * foreach node in tree->vm_avl_right: node->vm_avl_key >= tree->vm_avl_key.
+ */
+
+#ifdef DEBUG_AVL
+
+/* Look up the nodes at the left and at the right of a given node. */
+static void avl_neighbours (struct vm_area_struct * node, struct vm_area_struct * tree, struct vm_area_struct ** to_the_left, struct vm_area_struct ** to_the_right)
+{
+ vm_avl_key_t key = node->vm_avl_key;
+
+ *to_the_left = *to_the_right = NULL;
+ for (;;) {
+ if (tree == vm_avl_empty) {
+ printk("avl_neighbours: node not found in the tree\n");
+ return;
+ }
+ if (key == tree->vm_avl_key)
+ break;
+ if (key < tree->vm_avl_key) {
+ *to_the_right = tree;
+ tree = tree->vm_avl_left;
+ } else {
+ *to_the_left = tree;
+ tree = tree->vm_avl_right;
+ }
+ }
+ if (tree != node) {
+ printk("avl_neighbours: node not exactly found in the tree\n");
+ return;
+ }
+ if (tree->vm_avl_left != vm_avl_empty) {
+ struct vm_area_struct * node;
+ for (node = tree->vm_avl_left; node->vm_avl_right != vm_avl_empty; node = node->vm_avl_right)
+ continue;
+ *to_the_left = node;
+ }
+ if (tree->vm_avl_right != vm_avl_empty) {
+ struct vm_area_struct * node;
+ for (node = tree->vm_avl_right; node->vm_avl_left != vm_avl_empty; node = node->vm_avl_left)
+ continue;
+ *to_the_right = node;
+ }
+ if ((*to_the_left && ((*to_the_left)->vm_next != node)) || (node->vm_next != *to_the_right))
+ printk("avl_neighbours: tree inconsistent with list\n");
+}
+
+#endif
+
+/*
+ * Rebalance a tree.
+ * After inserting or deleting a node of a tree we have a sequence of subtrees
+ * nodes[0]..nodes[k-1] such that
+ * nodes[0] is the root and nodes[i+1] = nodes[i]->{vm_avl_left|vm_avl_right}.
+ */
+static void avl_rebalance (struct vm_area_struct *** nodeplaces_ptr, int count)
+{
+ for ( ; count > 0 ; count--) {
+ struct vm_area_struct ** nodeplace = *--nodeplaces_ptr;
+ struct vm_area_struct * node = *nodeplace;
+ struct vm_area_struct * nodeleft = node->vm_avl_left;
+ struct vm_area_struct * noderight = node->vm_avl_right;
+ int heightleft = heightof(nodeleft);
+ int heightright = heightof(noderight);
+ if (heightright + 1 < heightleft) {
+ /* */
+ /* * */
+ /* / \ */
+ /* n+2 n */
+ /* */
+ struct vm_area_struct * nodeleftleft = nodeleft->vm_avl_left;
+ struct vm_area_struct * nodeleftright = nodeleft->vm_avl_right;
+ int heightleftright = heightof(nodeleftright);
+ if (heightof(nodeleftleft) >= heightleftright) {
+ /* */
+ /* * n+2|n+3 */
+ /* / \ / \ */
+ /* n+2 n --> / n+1|n+2 */
+ /* / \ | / \ */
+ /* n+1 n|n+1 n+1 n|n+1 n */
+ /* */


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 16'
echo 'File patch-2.2.0-pre8 is continued in part 17'
echo 17 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Archive-name: v2.1/patch-2.2.0-pre8/part15

#!/bin/sh
# this is part 15 of a 17 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 15; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre8'
else
echo 'x - continuing with patch-2.2.0-pre8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre8' &&

+#define __RES_OUT(fds, n) (fds->res_out + n)
+#define __RES_EX(fds, n) (fds->res_ex + n)
X
-#define BITS(in) (*__IN(in)|*__OUT(in)|*__EX(in))
+#define BITS(fds, n) (*__IN(fds, n)|*__OUT(fds, n)|*__EX(fds, n))
X
-static int max_select_fd(unsigned long n, fd_set_buffer *fds)
+static int max_select_fd(unsigned long n, fd_set_bits *fds)
X {
- unsigned long *open_fds, *in;
+ unsigned long *open_fds;
X unsigned long set;
X int max;
X
@@ -70,10 +77,9 @@
X set = ~(~0UL << (n & (__NFDBITS-1)));
X n /= __NFDBITS;
X open_fds = current->files->open_fds.fds_bits+n;
- in = fds->in+n;
X max = 0;
X if (set) {
- set &= BITS(in);
+ set &= BITS(fds, n);
X if (set) {
X if (!(set & ~*open_fds))
X goto get_max;
@@ -81,10 +87,9 @@
X }
X }
X while (n) {
- in--;
X open_fds--;
X n--;
- set = BITS(in);
+ set = BITS(fds, n);
X if (!set)
X continue;
X if (set & ~*open_fds)
@@ -111,21 +116,22 @@
X #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
X #define POLLEX_SET (POLLPRI)
X
-int do_select(int n, fd_set_buffer *fds, long *timeout)
+int do_select(int n, fd_set_bits *fds, long *timeout)
X {
- poll_table wait_table, *wait;
- int retval, i;
+ poll_table *wait_table, *wait;
+ int retval, i, off;
X long __timeout = *timeout;
X
- wait = NULL;
+ wait = wait_table = NULL;
X if (__timeout) {
- struct poll_table_entry *entry = (struct poll_table_entry *) __get_free_page(GFP_KERNEL);
- if (!entry)
+ wait_table = (poll_table *) __get_free_page(GFP_KERNEL);
+ if (!wait_table)
X return -ENOMEM;
X
- wait_table.nr = 0;
- wait_table.entry = entry;
- wait = &wait_table;
+ wait_table->nr = 0;
+ wait_table->entry = (struct poll_table_entry *)(wait_table + 1);
+ wait_table->next = NULL;
+ wait = wait_table;
X }
X
X lock_kernel();
@@ -139,11 +145,11 @@


X current->state = TASK_INTERRUPTIBLE;

X for (i = 0 ; i < n; i++) {
X unsigned long bit = BIT(i);
- unsigned long *in = MEM(i,fds->in);
X unsigned long mask;
X struct file *file;
X
- if (!(bit & BITS(in)))
+ off = i / __NFDBITS;
+ if (!(bit & BITS(fds, off)))
X continue;
X /*
X * The poll_wait routine will increment f_count if
@@ -157,18 +163,18 @@
X if (file->f_op && file->f_op->poll)
X mask = file->f_op->poll(file, wait);
X }
- if ((mask & POLLIN_SET) && ISSET(bit, __IN(in))) {
- SET(bit, __RES_IN(in));
+ if ((mask & POLLIN_SET) && ISSET(bit, __IN(fds,off))) {
+ SET(bit, __RES_IN(fds,off));
X retval++;
X wait = NULL;
X }
- if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(in))) {
- SET(bit, __RES_OUT(in));
+ if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(fds,off))) {
+ SET(bit, __RES_OUT(fds,off));
X retval++;
X wait = NULL;
X }
- if ((mask & POLLEX_SET) && ISSET(bit, __EX(in))) {
- SET(bit, __RES_EX(in));
+ if ((mask & POLLEX_SET) && ISSET(bit, __EX(fds,off))) {
+ SET(bit, __RES_EX(fds,off));
X retval++;
X wait = NULL;
X }
@@ -181,10 +187,8 @@
X current->state = TASK_RUNNING;
X
X out:
- if (*timeout) {
- free_wait(&wait_table);
- free_page((unsigned long) wait_table.entry);
- }
+ if (*timeout)
+ free_wait(wait_table);
X
X /*
X * Up-to-date the caller timeout.
@@ -208,9 +212,10 @@
X asmlinkage int
X sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
X {
- fd_set_buffer *fds;
+ fd_set_bits fds;
+ char *bits;
X long timeout;
- int ret;
+ int ret, size;
X
X timeout = MAX_SCHEDULE_TIMEOUT;
X if (tvp) {
@@ -231,24 +236,35 @@
X }
X }
X
+ ret = -EINVAL;
+ if (n < 0 || n > KFDS_NR)
+ goto out_nofds;
+ /*
+ * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
+ * since we used fdset we need to allocate memory in units of
+ * long-words.
+ */
X ret = -ENOMEM;
- fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL);
- if (!fds)
+ size = FDS_BYTES(n);
+ bits = kmalloc(6 * size, GFP_KERNEL);
+ if (!bits)
X goto out_nofds;
- ret = -EINVAL;
- if (n < 0)
+ fds.in = (unsigned long *) bits;
+ fds.out = (unsigned long *) (bits + size);
+ fds.ex = (unsigned long *) (bits + 2*size);
+ fds.res_in = (unsigned long *) (bits + 3*size);
+ fds.res_out = (unsigned long *) (bits + 4*size);
+ fds.res_ex = (unsigned long *) (bits + 5*size);
+
+ if ((ret = get_fd_set(n, inp, fds.in)) ||
+ (ret = get_fd_set(n, outp, fds.out)) ||
+ (ret = get_fd_set(n, exp, fds.ex)))
X goto out;
- if (n > KFDS_NR)
- n = KFDS_NR;
- if ((ret = get_fd_set(n, inp, fds->in)) ||
- (ret = get_fd_set(n, outp, fds->out)) ||
- (ret = get_fd_set(n, exp, fds->ex)))
- goto out;
- zero_fd_set(n, fds->res_in);
- zero_fd_set(n, fds->res_out);
- zero_fd_set(n, fds->res_ex);
+ zero_fd_set(n, fds.res_in);
+ zero_fd_set(n, fds.res_out);
+ zero_fd_set(n, fds.res_ex);
X
- ret = do_select(n, fds, &timeout);
+ ret = do_select(n, &fds, &timeout);
X
X if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
X time_t sec = 0, usec = 0;
@@ -270,12 +286,12 @@
X ret = 0;
X }
X
- set_fd_set(n, inp, fds->res_in);
- set_fd_set(n, outp, fds->res_out);
- set_fd_set(n, exp, fds->res_ex);
+ set_fd_set(n, inp, fds.res_in);
+ set_fd_set(n, outp, fds.res_out);
+ set_fd_set(n, exp, fds.res_ex);
X
X out:
- free_page((unsigned long) fds);
+ kfree(bits);
X out_nofds:
X return ret;
X }
@@ -327,7 +343,7 @@
X {
X int i, fdcount, err, size;
X struct pollfd * fds, *fds1;
- poll_table wait_table, *wait = NULL;
+ poll_table *wait_table = NULL, *wait = NULL;
X
X lock_kernel();
X /* Do a sanity check on nfds ... */
@@ -338,20 +354,20 @@
X if (timeout) {
X /* Carefula about overflow in the intermediate values */
X if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
- timeout = (timeout*HZ+999)/1000+1;
+ timeout = (unsigned long)(timeout*HZ+999)/1000+1;
X else /* Negative or overflow */
X timeout = MAX_SCHEDULE_TIMEOUT;
X }
X
X err = -ENOMEM;
X if (timeout) {
- struct poll_table_entry *entry;
- entry = (struct poll_table_entry *) __get_free_page(GFP_KERNEL);
- if (!entry)
+ wait_table = (poll_table *) __get_free_page(GFP_KERNEL);
+ if (!wait_table)
X goto out;
- wait_table.nr = 0;
- wait_table.entry = entry;
- wait = &wait_table;
+ wait_table->nr = 0;
+ wait_table->entry = (struct poll_table_entry *)(wait_table + 1);
+ wait_table->next = NULL;
+ wait = wait_table;
X }
X
X size = nfds * sizeof(struct pollfd);
@@ -378,10 +394,8 @@
X out_fds:
X kfree(fds);
X out:
- if (wait) {
- free_wait(&wait_table);
- free_page((unsigned long) wait->entry);
- }
+ if (wait)
+ free_wait(wait_table);
X unlock_kernel();
X return err;
X }
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/balloc.c linux/fs/ufs/balloc.c
--- v2.2.0-pre7/linux/fs/ufs/balloc.c Fri Oct 23 22:01:22 1998
+++ linux/fs/ufs/balloc.c Sun Jan 17 18:32:26 1999
@@ -93,7 +93,7 @@
X ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);
X
X /*
- * Trying to reasembly free fragments into block
+ * Trying to reassemble free fragments into block
X */
X blkno = ufs_fragstoblks (bbase);
X if (ubh_isblockset(UCPI_UBH, ucpi->c_freeoff, blkno)) {
@@ -436,7 +436,7 @@
X fragsize = i - oldcount;
X if (!SWAB32(ucg->cg_frsum[fragsize]))
X ufs_panic (sb, "ufs_add_fragments",
- "internal error or corruted bitmap on cg %u", cgno);
+ "internal error or corrupted bitmap on cg %u", cgno);
X DEC_SWAB32(ucg->cg_frsum[fragsize]);
X if (fragsize != count)
X INC_SWAB32(ucg->cg_frsum[fragsize - count]);
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/cylinder.c linux/fs/ufs/cylinder.c
--- v2.2.0-pre7/linux/fs/ufs/cylinder.c Fri Oct 23 22:01:22 1998
+++ linux/fs/ufs/cylinder.c Sun Jan 17 18:32:26 1999


@@ -86,7 +86,7 @@
X }

X
X /*
- * Remove cylinder group from cache, does'n release memory
+ * Remove cylinder group from cache, doesn't release memory
X * allocated for cylinder group (this is done at ufs_put_super only).
X */
X void ufs_put_cylinder (struct super_block * sb, unsigned bitmap_nr)
@@ -132,7 +132,7 @@
X * Find cylinder group in cache and return it as pointer.
X * If cylinder group is not in cache, we will load it from disk.
X *
- * The cache is managed by LRU alghoritm.
+ * The cache is managed by LRU algorithm.
X */
X struct ufs_cg_private_info * ufs_load_cylinder (
X struct super_block * sb, unsigned cgno)
@@ -161,7 +161,7 @@
X if (uspi->s_ncg <= UFS_MAX_GROUP_LOADED) {
X if (sb->u.ufs_sb.s_cgno[cgno] != UFS_CGNO_EMPTY) {
X if (sb->u.ufs_sb.s_cgno[cgno] != cgno) {
- ufs_panic (sb, "ufs_load_cylinder", "internal error, wrog number of cg in cache");
+ ufs_panic (sb, "ufs_load_cylinder", "internal error, wrong number of cg in cache");
X UFSD(("EXIT (FAILED)\n"))
X return NULL;
X }
@@ -191,7 +191,7 @@
X sb->u.ufs_sb.s_ucpi[0] = ucpi;
X /*
X * Cylinder group number cg is not in cache, we will read it from disk
- * and put it to the first possition
+ * and put it to the first position
X */
X } else {
X if (sb->u.ufs_sb.s_cg_loaded < UFS_MAX_GROUP_LOADED)
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/dir.c linux/fs/ufs/dir.c
--- v2.2.0-pre7/linux/fs/ufs/dir.c Fri Jan 8 22:36:14 1999
+++ linux/fs/ufs/dir.c Thu Jan 14 10:31:41 1999
@@ -14,6 +14,7 @@
X */
X
X #include <linux/fs.h>
+#include <linux/ufs_fs.h>
X
X #include "swab.h"
X #include "util.h"
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/file.c linux/fs/ufs/file.c
--- v2.2.0-pre7/linux/fs/ufs/file.c Wed Aug 26 11:37:43 1998
+++ linux/fs/ufs/file.c Thu Jan 14 10:31:41 1999
@@ -41,9 +41,6 @@
X #define MIN(a,b) (((a)<(b))?(a):(b))
X #define MAX(a,b) (((a)>(b))?(a):(b))
X
-#include <linux/fs.h>
-#include <linux/ufs_fs.h>
-
X static long long ufs_file_lseek(struct file *, long long, int);
X static ssize_t ufs_file_write (struct file *, const char *, size_t, loff_t *);
X static int ufs_release_file (struct inode *, struct file *);
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/ialloc.c linux/fs/ufs/ialloc.c
--- v2.2.0-pre7/linux/fs/ufs/ialloc.c Fri Oct 23 22:01:22 1998
+++ linux/fs/ufs/ialloc.c Sun Jan 17 18:32:26 1999
@@ -150,7 +150,7 @@
X * the groups with above-average free space, that group with the fewest
X * directories already is chosen.
X *
- * For other inodes, search forward from the parent directory\'s block
+ * For other inodes, search forward from the parent directory's block
X * group to find a free inode.
X */
X struct inode * ufs_new_inode (const struct inode * dir, int mode, int * err )
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/inode.c linux/fs/ufs/inode.c
--- v2.2.0-pre7/linux/fs/ufs/inode.c Fri Oct 23 22:01:22 1998
+++ linux/fs/ufs/inode.c Sun Jan 17 18:32:26 1999
@@ -1,5 +1,5 @@
X /*
- * linux/ufs/ufs/inode.c
+ * linux/fs/ufs/inode.c
X *
X * Copyright (C) 1998
X * Daniel Pirkl <daniel...@email.cz>
@@ -254,7 +254,7 @@
X SWAB32(*p), required + (blockoff - lastblockoff), err);
X }
X /*
- * We will allocated new block before last allocat block
+ * We will allocate new block before last allocated block
X */
X else /* (lastblock > block) */ {
X if (lastblock && (tmp = SWAB32(inode->u.ufs_i.i_u1.i_data[lastblock-1])))
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.2.0-pre7/linux/fs/ufs/namei.c Wed Jan 13 15:00:43 1999
+++ linux/fs/ufs/namei.c Sun Jan 17 18:32:26 1999
@@ -58,8 +58,7 @@
X /*
X * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure.
X *
- * len <= UFS_MAXNAMLEN' is guaranteed by caller.
- * de != NULL' is guaranteed by caller.
+ * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller.
X */
X static inline int ufs_match (int len, const char * const name,
X struct ufs_dir_entry * de, unsigned flags, unsigned swab)
@@ -144,7 +143,7 @@
X dlimit = bh->b_data + sb->s_blocksize;
X while ((char *) de < dlimit && offset < dir->i_size) {
X /* this code is executed quadratically often */
- /* do minimal checking by hand' */
+ /* do minimal checking by hand */
X int de_len;
X
X if ((char *) de + namelen <= dlimit &&
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.2.0-pre7/linux/fs/ufs/super.c Wed Jan 13 15:00:43 1999
+++ linux/fs/ufs/super.c Sun Jan 17 18:32:26 1999
@@ -6,7 +6,7 @@
X * Charles University, Faculty of Mathematics and Physics
X */
X
-/* Derivated from
+/* Derived from
X *
X * linux/fs/ext2/super.c
X *
@@ -26,7 +26,7 @@


X */
X
X /*

- * Inspirated by
+ * Inspired by
X *
X * linux/fs/ufs/super.c
X *
@@ -92,7 +92,7 @@
X
X #ifdef UFS_SUPER_DEBUG_MORE
X /*
- * Print contents of ufs_super_block, useful for debuging
+ * Print contents of ufs_super_block, useful for debugging
X */
X void ufs_print_super_stuff(struct ufs_super_block_first * usb1,
X struct ufs_super_block_second * usb2,
@@ -137,7 +137,7 @@
X
X
X /*
- * Print contents of ufs_cylinder_group, useful for debuging
+ * Print contents of ufs_cylinder_group, useful for debugging
X */
X void ufs_print_cylinder_stuff(struct ufs_cylinder_group *cg, unsigned swab)
X {
@@ -231,10 +231,6 @@
X sb->s_flags |= MS_RDONLY;
X printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n",
X kdevname(sb->s_dev), function, error_buf);
-/***
- panic ("UFS-fs panic (device %s): %s: %s\n",
- kdevname(sb->s_dev), function, error_buf);
-***/
X }
X
X void ufs_warning (struct super_block * sb, const char * function,
@@ -309,7 +305,7 @@
X }
X
X /*
- * Read on-disk structures asscoiated with cylinder groups
+ * Read on-disk structures associated with cylinder groups
X */
X int ufs_read_cylinder_structures (struct super_block * sb) {
X struct ufs_sb_private_info * uspi;
@@ -391,7 +387,7 @@
X }
X
X /*
- * Put on-disk structures associated with cylidner groups and
+ * Put on-disk structures associated with cylinder groups and
X * write them back to disk
X */
X void ufs_put_cylinder_structures (struct super_block * sb) {
@@ -466,10 +462,10 @@
X goto failed;
X }
X if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) {
- printk("You didn't specify type of your ufs file system\n\n"
+ printk("You didn't specify the type of your ufs filesystem\n\n"
X " mount -t ufs -o ufstype=sun|44bsd|old|next|openstep ....\n\n"
- "!!! WARNING !!! wrong value may corrupt you file system\n"
- "default value is ufstype=old\n");
+ ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, "
+ "default is ufstype=old\n");
X ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD);
X }
X
@@ -480,7 +476,7 @@
X
X switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) {
X case UFS_MOUNT_UFSTYPE_44BSD:
- UFSD(("44bsd ufstype\n"))
+ UFSD(("ufstype=44bsd\n"))
X uspi->s_fsize = block_size = 512;
X uspi->s_fmask = ~(512 - 1);
X uspi->s_fshift = 9;
@@ -490,7 +486,7 @@
X break;
X
X case UFS_MOUNT_UFSTYPE_SUN:
- UFSD(("sun ufstype\n"))
+ UFSD(("ufstype=sun\n"))
X uspi->s_fsize = block_size = 1024;
X uspi->s_fmask = ~(1024 - 1);
X uspi->s_fshift = 10;
@@ -500,7 +496,7 @@
X break;
X
X case UFS_MOUNT_UFSTYPE_OLD:
- UFSD(("old ufstype\n"))
+ UFSD(("ufstype=old\n"))
X uspi->s_fsize = block_size = 1024;
X uspi->s_fmask = ~(1024 - 1);
X uspi->s_fshift = 10;
@@ -508,13 +504,13 @@
X uspi->s_sbbase = 0;
X flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
X if (!(sb->s_flags & MS_RDONLY)) {
- printk("old type of ufs is supported read-only\n");
+ printk(KERN_INFO "ufstype=old is supported read-only\n");
X sb->s_flags |= MS_RDONLY;
X }
X break;
X
X case UFS_MOUNT_UFSTYPE_NEXT:
- UFSD(("next ufstype\n"))
+ UFSD(("ufstype=next\n"))
X uspi->s_fsize = block_size = 1024;
X uspi->s_fmask = ~(1024 - 1);
X uspi->s_fshift = 10;
@@ -522,13 +518,13 @@
X uspi->s_sbbase = 0;
X flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
X if (!(sb->s_flags & MS_RDONLY)) {
- printk("nextstep type of ufs is supported read-only\n");
+ printk(KERN_INFO "ufstype=next is supported read-only\n");
X sb->s_flags |= MS_RDONLY;
X }
X break;
X
X case UFS_MOUNT_UFSTYPE_OPENSTEP:
- UFSD(("openstep ufstype\n"))
+ UFSD(("ufstype=openstep\n"))
X uspi->s_fsize = block_size = 1024;
X uspi->s_fmask = ~(1024 - 1);
X uspi->s_fshift = 10;
@@ -536,13 +532,13 @@
X uspi->s_sbbase = 0;
X flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
X if (!(sb->s_flags & MS_RDONLY)) {
- printk("openstep type of ufs is supported read-only\n");
+ printk(KERN_INFO "ufstype=openstep is supported read-only\n");
X sb->s_flags |= MS_RDONLY;
X }
X break;
X
X default:
- printk("this fs type of ufs is not supported\n");
+ printk("unknown ufstype\n");
X goto failed;
X }
X
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/ufs/symlink.c linux/fs/ufs/symlink.c
--- v2.2.0-pre7/linux/fs/ufs/symlink.c Mon Sep 28 10:51:35 1998
+++ linux/fs/ufs/symlink.c Thu Jan 14 10:31:41 1999
@@ -1,5 +1,5 @@
X /*
- * linux/ufs/ufs/symlink.c
+ * linux/fs/ufs/symlink.c
X *
X * Copyright (C) 1998
X * Daniel Pirkl <daniel...@emai.cz>
@@ -27,7 +27,7 @@
X
X #include <linux/errno.h>
X #include <linux/fs.h>
-#include <linux/ext2_fs.h>
+#include <linux/ufs_fs.h>
X #include <linux/sched.h>
X #include <linux/mm.h>
X #include <linux/stat.h>
diff -u --recursive --new-file v2.2.0-pre7/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.2.0-pre7/linux/fs/vfat/namei.c Thu Jan 7 15:11:40 1999
+++ linux/fs/vfat/namei.c Fri Jan 15 11:52:40 1999
@@ -395,7 +395,7 @@
X static char replace_chars[] = "[];,+=";
X
X static int vfat_find(struct inode *dir,struct qstr* name,
- int find_long,int new_filename,int is_dir,
+ int new_filename,int is_dir,
X struct vfat_slot_info *sinfo_out);
X
X /* Checks the validity of a long MS-DOS filename */
@@ -446,12 +446,11 @@
X static int vfat_valid_shortname(const char *name,int len,
X int dot_dirs, int utf8)
X {
- const char *walk, **reserved;
+ const char *walk;
X unsigned char c;
X int space;
X int baselen;
X
- if (IS_FREE(name)) return -EINVAL;
X if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
X if (!dot_dirs) return -EEXIST;
X return 1;
@@ -463,11 +462,9 @@
X c = *walk++;
X len--;
X if (utf8 && (c & 0x80)) return -EINVAL;
- if (strchr(bad_chars,c)) return -EINVAL;
X if (strchr(replace_chars,c)) return -EINVAL;
X if (c >= 'A' && c <= 'Z') return -EINVAL;
- if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
- if ((walk == name) && (c == 0xE5)) c = 0x05;
+ if (c < ' '|| c==':') return -EINVAL;
X if (c == '.') break;
X space = c == ' ';
X }
@@ -477,51 +474,52 @@
X len--;
X if (c != '.') return -EINVAL;
X }
- while (c != '.' && len--) c = *walk++;
X baselen = walk - name;
X if (c == '.') {
X baselen--;
X if (len >= 4) return -EINVAL;
- while (len > 0 && walk-name < (MSDOS_NAME+1)) {
+ while (len > 0) {
X c = *walk++;
X len--;
X if (utf8 && (c & 0x80)) return -EINVAL;
- if (strchr(bad_chars,c)) return -EINVAL;
X if (strchr(replace_chars,c))
X return -EINVAL;
- if (c < ' ' || c == ':' || c == '\\' || c == '.')
+ if (c < ' ' || c == '.'|| c==':')
X return -EINVAL;
X if (c >= 'A' && c <= 'Z') return -EINVAL;
X space = c == ' ';
X }
X if (space) return -EINVAL;
- if (len) return -EINVAL;
- }
- if (baselen == 3) {
- for (reserved = reserved3_names; *reserved; reserved++)
- if (!strnicmp(name,*reserved,baselen)) return -EINVAL;
- } else if (baselen == 4) {
- for (reserved = reserved4_names; *reserved; reserved++)
- if (!strnicmp(name,*reserved,baselen)) return -EINVAL;
X }
X

X return 0;
X }
X

-/* Takes a short filename and converts it to a formatted MS-DOS filename.
- * If the short filename is not a valid MS-DOS filename, an error is
- * returned. The formatted short filename is returned in 'res'.
- */
+static int vfat_find_form(struct inode *dir,char *name)
+{
+ struct msdos_dir_entry *de;
+ struct buffer_head *bh = NULL;
+ loff_t pos = 0;
+
+ while(fat_get_entry(dir, &pos, &bh, &de) >= 0) {
+ if (de->attr == ATTR_EXT)
+ continue;
+ if (memcmp(de->name,name,MSDOS_NAME))
+ continue;
+ brelse(bh);
+ return 0;
+ }
+ brelse(bh);
+ return -ENOENT;
+}
X
X static int vfat_format_name(const char *name,int len,char *res,
X int dot_dirs,int utf8)
X {
X char *walk;
- const char **reserved;
X unsigned char c;
X int space;
X
- if (IS_FREE(name)) return -EINVAL;
X if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
X if (!dot_dirs) return -EEXIST;
X memset(res+1,' ',10);
@@ -530,36 +528,25 @@
X }
X
X space = 1; /* disallow names starting with a dot */
- c = 0;
- for (walk = res; len && walk-res < 8; walk++) {
- c = *name++;
- len--;
+ for (walk = res; len-- && (c=*name++)!='.' ; walk++) {
+ if (walk-res == 8) return -EINVAL;
X if (utf8 && (c & 0x80)) return -EINVAL;
- if (strchr(bad_chars,c)) return -EINVAL;
X if (strchr(replace_chars,c)) return -EINVAL;
X if (c >= 'A' && c <= 'Z') return -EINVAL;
- if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
- if (c == '.') break;
+ if (c < ' '|| c==':') return -EINVAL;
X space = c == ' ';
X *walk = c >= 'a' && c <= 'z' ? c-32 : c;
X }
X if (space) return -EINVAL;
- if (len && c != '.') {
- c = *name++;
- len--;
- if (c != '.') return -EINVAL;
- }
- while (c != '.' && len--) c = *name++;
- if (c == '.') {
+ if (len >= 0) {
X while (walk-res < 8) *walk++ = ' ';
X while (len > 0 && walk-res < MSDOS_NAME) {
X c = *name++;
X len--;
X if (utf8 && (c & 0x80)) return -EINVAL;
- if (strchr(bad_chars,c)) return -EINVAL;
X if (strchr(replace_chars,c))
X return -EINVAL;
- if (c < ' ' || c == ':' || c == '\\' || c == '.')
+ if (c < ' ' || c == '.'|| c==':')
X return -EINVAL;
X if (c >= 'A' && c <= 'Z') return -EINVAL;
X space = c == ' ';
@@ -569,10 +556,6 @@
X if (len) return -EINVAL;
X }
X while (walk-res < MSDOS_NAME) *walk++ = ' ';
- for (reserved = reserved3_names; *reserved; reserved++)
- if (!strnicmp(res,*reserved,8)) return -EINVAL;
- for (reserved = reserved4_names; *reserved; reserved++)
- if (!strnicmp(res,*reserved,8)) return -EINVAL;
X
X return 0;
X }
@@ -587,16 +570,12 @@
X {
X const char *ip, *ext_start, *end;
X char *p;
- int sz, extlen, baselen, totlen;
+ int sz, extlen, baselen;
X char msdos_name[13];
X char base[9], ext[4];
X int i;
- int res;
- int spaces;
X char buf[8];
- struct vfat_slot_info sinfo;
X const char *name_start;
- struct qstr qname;
X
X PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));
X sz = 0; /* Make compiler happy */
@@ -606,31 +585,25 @@
X * shortname if is were all capitalized. However, do not
X * allow spaces in short names because Win95 scandisk does
X * not like that */
- res = 0;
- for (i = 0, p = msdos_name, ip = name; i < len; i++, p++, ip++)
- {
- if (*ip == ' ') {
- res = -1;
- break;
+ for (i = 0, p = msdos_name, ip = name; ; i++, p++, ip++) {
+ if (i == len) {
+ if (vfat_format_name(msdos_name,
+ len, name_res, 1, utf8) < 0)
+ break;
+ PRINTK3(("vfat_create_shortname 1\n"));
+ if (vfat_find_form(dir, name_res) < 0)
+ return 0;
+ return -EEXIST;
X }
+
+ if (*ip == ' ')
+ break;
X if (*ip >= 'A' && *ip <= 'Z') {
X *p = *ip + 32;
X } else {
X *p = *ip;
X }
X }
- if (res == 0) {
- res = vfat_format_name(msdos_name, len, name_res, 1, utf8);
- }
- if (res > -1) {
- PRINTK3(("vfat_create_shortname 1\n"));
- qname.name=msdos_name;
- qname.len=len;
- res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
- PRINTK3(("vfat_create_shortname 2\n"));
- if (res > -1) return -EEXIST;


- return 0;
- }
X }
X

X PRINTK3(("vfat_create_shortname 3\n"));
@@ -675,8 +648,8 @@
X *p++ = '_';
X baselen++;
X } else if (!strchr(skip_chars, *ip)) {
- if (*ip >= 'A' && *ip <= 'Z') {
- *p = *ip + 32;
+ if (*ip >= 'a' && *ip <= 'z') {
+ *p = *ip - 32;
X } else {
X *p = *ip;


X }
@@ -689,17 +662,15 @@

X return -EINVAL;
X }
X
- spaces = 8 - baselen;
-
+ extlen = 0;
X if (ext_start) {
- extlen = 0;
X for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
X if (utf8 && (*ip & 0x80)) {
X *p++ = '_';
X extlen++;
X } else if (!strchr(skip_chars, *ip)) {
- if (*ip >= 'A' && *ip <= 'Z') {
- *p = *ip + 32;
+ if (*ip >= 'a' && *ip <= 'z') {
+ *p = *ip - 32;
X } else {
X *p = *ip;
X }
@@ -708,74 +679,57 @@
X p++;
X }
X }
- } else {
- extlen = 0;
X }
X ext[extlen] = '\0';
X base[baselen] = '\0';
X
- strcpy(msdos_name, base);
- msdos_name[baselen] = '.';
- strcpy(&msdos_name[baselen+1], ext);
+ /* Yes, it can happen. ".\xe5" would do it. */
+ if (IS_FREE(base))
+ base[0]='_';
+
+ /* OK, at this point we know that base is not longer than 8 symbols,
+ * ext is not longer than 3, base is nonempty, both don't contain
+ * any bad symbols (lowercase transformed to uppercase).
+ */
X
- totlen = baselen + extlen + (extlen > 0);
- res = 0;
- if (MSDOS_SB(dir->i_sb)->options.numtail == 0) {
- qname.name=msdos_name;
- qname.len=totlen;
- res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
- }
+ memset(name_res, ' ', MSDOS_NAME);
+ memcpy(name_res,base,baselen);
+ memcpy(name_res+8,ext,extlen);
+ if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
+ if (vfat_find_form(dir, name_res) < 0)
+ return 0;
X
- if (res > -1) {
- /*
- * Try to find a unique extension. This used to
- * iterate through all possibilities sequentially,
- * but that gave extremely bad performance. Windows
- * only tries a few cases before using random
- * values for part of the base.
- */
+ /*
+ * Try to find a unique extension. This used to
+ * iterate through all possibilities sequentially,
+ * but that gave extremely bad performance. Windows
+ * only tries a few cases before using random
+ * values for part of the base.
+ */
X
- if (2 > spaces) {
- baselen = baselen - (2 - spaces);
- spaces = 2;
- }
- msdos_name[baselen] = '~';
- msdos_name[baselen+2] = '.';
- strcpy(&msdos_name[baselen+3], ext);
- totlen = baselen + 2 + extlen + (extlen > 0);
- qname.name=msdos_name;
- qname.len=totlen;
- for (i = 1; res > -1 && i < 10; i++) {
- strncpy(msdos_name, base, baselen);
- msdos_name[baselen+1] = i + '0';
- res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
- }
- }
- if (res > -1) {
- i = jiffies & 0xffff;
- sz = (jiffies >> 16) & 0x7;
- if (6 > spaces) {
- baselen = baselen - (6 - spaces);
- spaces = 6;
- }
- msdos_name[baselen+4] = '~';
- msdos_name[baselen+5] = '1' + sz;
- msdos_name[baselen+6] = '.';
- strcpy(&msdos_name[baselen+7], ext);
- totlen = baselen + 6 + extlen + (extlen > 0);
- qname.name=msdos_name;
- qname.len=totlen;
- while (res > -1) {
- sprintf(buf, "%04x", i);
- memcpy(&msdos_name[baselen], buf, 4);
- msdos_name[12] = 0;
- res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
- i -= 11;
- }
+ if (baselen>6)
+ baselen = 6;
+ name_res[baselen] = '~';
+ for (i = 1; i < 10; i++) {
+ name_res[baselen+1] = i + '0';
+ if (vfat_find_form(dir, name_res) < 0)


+ return 0;
X }
X

- res = vfat_format_name(msdos_name, totlen, name_res, 1, utf8);
- return res;
+ i = jiffies & 0xffff;
+ sz = (jiffies >> 16) & 0x7;
+ if (baselen>2)
+ baselen = 2;
+ name_res[baselen+4] = '~';
+ name_res[baselen+5] = '1' + sz;
+ while (1) {
+ sprintf(buf, "%04X", i);
+ memcpy(&name_res[baselen], buf, 4);
+ if (vfat_find_form(dir, name_res) < 0)
+ break;
+ i -= 11;
+ }


+ return 0;
X }
X

X static loff_t vfat_find_free_slots(struct inode *dir,int slots)
@@ -996,6 +950,10 @@
X strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
X } else {
X PRINTK3(("vfat_build_slots 4\n"));
+ res = vfat_valid_longname(name, len, 1, xlate);
+ if (res < 0) {
+ return res;
+ }
X res = vfat_valid_shortname(name, len, 1, utf8);
X if (res > -1) {
X PRINTK3(("vfat_build_slots 5a\n"));
@@ -1007,11 +965,6 @@
X return res;
X }
X
- res = vfat_valid_longname(name, len, 1, xlate);
- if (res < 0) {
- return res;
- }
-
X *is_long = 1;
X
X return vfat_fill_long_slots(ds, name, len, msdos_name,
@@ -1066,7 +1019,7 @@
X }
X
X static int vfat_find(struct inode *dir,struct qstr* qname,
- int find_long, int new_filename,int is_dir,struct vfat_slot_info *sinfo_out)
+ int new_filename,int is_dir,struct vfat_slot_info *sinfo_out)
X {
X struct super_block *sb = dir->i_sb;
X struct vfat_find_info vf;
@@ -1096,7 +1049,7 @@
X vf.found = 0;
X vf.posix = MSDOS_SB(sb)->options.posixfs;
X vf.anycase = (MSDOS_SB(sb)->options.name_check != 's');
- res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,find_long,0);
+ res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,1,0);
X PRINTK3(("vfat_find: Debug 1\n"));
X if (res < 0) goto cleanup;
X if (vf.found) {
@@ -1117,75 +1070,70 @@
X }
X
X PRINTK3(("vfat_find: Debug 3\n"));
- if (!vf.found && !new_filename) {
+ if (!new_filename) {
X res = -ENOENT;
X goto cleanup;
X }
X
X res = vfat_build_slots(dir, qname->name, vf.len, ds,
X &slots, &is_long);
+ /* Here we either have is_long and slots>=0 or slots==1 */
X if (res < 0) goto cleanup;
X
X de = (struct msdos_dir_entry *) ds;
X
X bh = NULL;
- if (new_filename) {
- PRINTK3(("vfat_find: create file 1\n"));
- if (is_long) slots++;
- offset = vfat_find_free_slots(dir, slots);
- if (offset < 0) {
- res = offset;
+
+ PRINTK3(("vfat_find: create file 1\n"));
+ if (is_long) slots++;
+ offset = vfat_find_free_slots(dir, slots);
+ if (offset < 0) {
+ res = offset;
+ goto cleanup;
+ }
+
+ PRINTK3(("vfat_find: create file 2\n"));
+ /* Now create the new entry */
+ bh = NULL;
+ for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
+ PRINTK3(("vfat_find: create file 3, slot=%d\n",slot));
+ sinfo_out->ino = fat_get_entry(dir,&offset,&bh,&de);
+ if (sinfo_out->ino < 0) {
+ PRINTK3(("vfat_find: problem\n"));
+ res = sinfo_out->ino;
X goto cleanup;
X }
+ memcpy(de, ps, sizeof(struct msdos_dir_slot));
+ fat_mark_buffer_dirty(sb, bh, 1);
+ }
X
- PRINTK3(("vfat_find: create file 2\n"));
- /* Now create the new entry */
- bh = NULL;
- for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
- PRINTK3(("vfat_find: create file 3, slot=%d\n",slot));
- sinfo_out->ino = fat_get_entry(dir,&offset,&bh,&de);
- if (sinfo_out->ino < 0) {
- PRINTK3(("vfat_find: problem\n"));
- res = sinfo_out->ino;
- goto cleanup;
- }
- memcpy(de, ps, sizeof(struct msdos_dir_slot));
- fat_mark_buffer_dirty(sb, bh, 1);
- }
+ PRINTK3(("vfat_find: create file 4\n"));
+ dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
+ mark_inode_dirty(dir);
X
- PRINTK3(("vfat_find: create file 4\n"));
- dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
- mark_inode_dirty(dir);
-
- PRINTK3(("vfat_find: create file 5\n"));
-
- fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
- de->ctime_ms = 0;
- de->ctime = de->time;
- de->adate = de->cdate = de->date;
- de->start = 0;
- de->starthi = 0;
- de->size = 0;
- de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
- de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
+ PRINTK3(("vfat_find: create file 5\n"));
X
+ fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
+ de->ctime_ms = 0;
+ de->ctime = de->time;
+ de->adate = de->cdate = de->date;
+ de->start = 0;
+ de->starthi = 0;
+ de->size = 0;
+ de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
+ de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
X
- fat_mark_buffer_dirty(sb, bh, 1);
- fat_brelse(sb, bh);
X
- sinfo_out->is_long = (slots > 1) ? 1 : 0;
- if (sinfo_out->is_long) {
- sinfo_out->long_slots = slots - 1;
- } else {
- sinfo_out->long_slots = 0;
- }
- sinfo_out->total_slots = slots;
- sinfo_out->shortname_offset = offset - sizeof(struct msdos_dir_slot);
- sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
- res = 0;
- } else {
- res = -ENOENT;
- }
+ fat_mark_buffer_dirty(sb, bh, 1);
+ fat_brelse(sb, bh);
+
+ /* slots can't be less than 1 */
+ sinfo_out->is_long = (slots > 1);
+ sinfo_out->long_slots = slots - 1;
+ sinfo_out->total_slots = slots;
+ sinfo_out->shortname_offset = offset - sizeof(struct msdos_dir_slot);
+ sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
+ res = 0;
X
X cleanup:
X kfree(ds);
@@ -1206,7 +1154,7 @@
X dentry->d_op = &vfat_dentry_ops[table];
X
X result = NULL;
- if ((res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo)) < 0) {
+ if ((res = vfat_find(dir,&dentry->d_name,0,0,&sinfo)) < 0) {
X result = NULL;
X table++;
X goto error;
@@ -1242,7 +1190,7 @@
X
X *result=0;
X PRINTK1(("vfat_create_entry: Entering\n"));
- res = vfat_find(dir, qname, 1, 1, is_dir, &sinfo);
+ res = vfat_find(dir, qname, 1, is_dir, &sinfo);
X if (res < 0) {
X return res;
X }
@@ -1387,9 +1335,6 @@
X struct buffer_head *bh;
X struct msdos_dir_entry *de;
X
- if (dir->i_count > 1) {
- return -EBUSY;
- }
X if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
X pos = 0;
X bh = NULL;
@@ -1410,88 +1355,50 @@


X return 0;
X }
X

-static int vfat_rmdir_free_ino(struct inode *dir,struct buffer_head *bh,
- struct msdos_dir_entry *de,struct dentry* dentry)
+static void vfat_free_ino(struct inode *dir,struct buffer_head *bh,
+ struct msdos_dir_entry *de,struct inode* victim)
X {
X struct super_block *sb = dir->i_sb;
- int res;
-
- if (!list_empty(&dentry->d_hash))
- return -EBUSY;
-
- res = vfat_empty(dentry->d_inode);
- if (res) {
- return res;
- }
- dentry->d_inode->i_nlink = 0;
- dentry->d_inode->i_mtime = dir->i_mtime = CURRENT_TIME;
- dentry->d_inode->i_atime = dir->i_atime = CURRENT_TIME;
- dir->i_nlink--;
- mark_inode_dirty(dir);
- mark_inode_dirty(dentry->d_inode);
- de->name[0] = DELETED_FLAG;
- fat_mark_buffer_dirty(sb, bh, 1);
-


- return 0;
-}
-

-static int vfat_unlink_free_ino(struct inode *dir,struct buffer_head *bh,
- struct msdos_dir_entry *de,struct dentry* dentry,int nospc)
-{
- struct super_block *sb = dir->i_sb;
- if ((!S_ISREG(dentry->d_inode->i_mode) && nospc) ||
- IS_IMMUTABLE(dentry->d_inode)) {
- return -EPERM;
- }
- dentry->d_inode->i_nlink = 0;
- dentry->d_inode->i_mtime = dir->i_mtime = CURRENT_TIME;
- dentry->d_inode->i_atime = dir->i_atime = CURRENT_TIME;
+ victim->i_nlink = 0;
+ victim->i_mtime = dir->i_mtime = CURRENT_TIME;
+ victim->i_atime = dir->i_atime = CURRENT_TIME;
X dir->i_version = ++event;
- MSDOS_I(dentry->d_inode)->i_busy = 1;
+ MSDOS_I(victim)->i_busy = 1;
X mark_inode_dirty(dir);
- mark_inode_dirty(dentry->d_inode);
+ mark_inode_dirty(victim);
X de->name[0] = DELETED_FLAG;
X fat_mark_buffer_dirty(sb, bh, 1);
-
- return 0;
X }
X
X static int vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
- struct buffer_head **bh,struct dentry* dentry,
- int is_dir,int nospc)
+ struct inode* victim)
X {
X struct super_block *sb = dir->i_sb;
X loff_t offset;
+ struct buffer_head *bh=NULL;
X struct msdos_dir_entry *de;
X int res, i;
X
X /* remove the shortname */
X offset = sinfo->shortname_offset;
- res = fat_get_entry(dir, &offset, bh, &de);
+ res = fat_get_entry(dir, &offset, &bh, &de);
X if (res < 0) return res;
- if (is_dir) {
- res = vfat_rmdir_free_ino(dir,*bh,de,dentry);
- } else {
- res = vfat_unlink_free_ino(dir,*bh,de,dentry,nospc);
- }
- if (res < 0) return res;
-
+ vfat_free_ino(dir,bh,de,victim);
X /* remove the longname */
X offset = sinfo->longname_offset;
X for (i = sinfo->long_slots; i > 0; --i) {
- res = fat_get_entry(dir, &offset, bh, &de);
- if (res < 0) {
+ if (fat_get_entry(dir, &offset, &bh, &de) < 0)
X continue;
- }
X de->name[0] = DELETED_FLAG;
X de->attr = 0;
- fat_mark_buffer_dirty(sb, *bh, 1);
+ fat_mark_buffer_dirty(sb, bh, 1);
X }
+ if (bh) fat_brelse(sb, bh);


X return 0;
X }
X

-/* Replace inodes in alias dentries and drop all but the initial dentry */
-static void drop_replace_inodes(struct dentry *dentry, struct inode *inode)
+/* Drop all aliases */
+static void drop_aliases(struct dentry *dentry)
X {
X struct list_head *head, *next, *tmp;
X struct dentry *alias;
@@ -1507,12 +1414,6 @@
X if (alias == dentry)
X continue;
X
- if (inode) {
- list_del(&alias->d_alias);
- iput(alias->d_inode);
- d_instantiate(alias, inode);
- inode->i_count++;
- }
X d_drop(alias);
X }
X }
@@ -1520,22 +1421,30 @@
X
X static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
X {
- struct super_block *sb = dir->i_sb;
X int res;
- struct buffer_head *bh;
X struct vfat_slot_info sinfo;
X
X PRINTK1(("vfat_rmdirx: dentry=%p\n", dentry));
- res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
+ res = vfat_find(dir,&dentry->d_name,0,0,&sinfo);
X
X if (res >= 0 && sinfo.total_slots > 0) {
- bh = NULL;
- res = vfat_remove_entry(dir,&sinfo,&bh,dentry,1,0);
- if (res > 0) {
+ if (!list_empty(&dentry->d_hash))
+ return -EBUSY;
+ /* Take care of aliases */
+ if (dentry->d_inode->i_count > 1) {
+ shrink_dcache_parent(dentry->d_parent);
+ if (dentry->d_inode->i_count > 1)
+ return -EBUSY;
+ }
+ res = vfat_empty(dentry->d_inode);
+ if (res)
+ return res;
+
+ res = vfat_remove_entry(dir,&sinfo,dentry->d_inode);
+ if (res >= 0) {
+ dir->i_nlink--;
X res = 0;
X }
- dir->i_version = ++event;
- if (bh) fat_brelse(sb, bh);
X }
X return res;
X }
@@ -1549,10 +1458,7 @@
X res = -EBUSY;
X if (list_empty(&dentry->d_hash)) {
X res = vfat_rmdirx(dir, dentry);
- if (res >= 0) {
- drop_replace_inodes(dentry, NULL);
- d_delete(dentry);
- }
+ /* If that went OK all aliases are already dropped */
X }
X return res;
X }
@@ -1562,23 +1468,22 @@
X struct dentry* dentry,
X int nospc) /* Flag special file ? */
X {
- struct super_block *sb = dir->i_sb;
X int res;
- struct buffer_head *bh;
X struct vfat_slot_info sinfo;
X
X PRINTK1(("vfat_unlinkx: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
- bh = NULL;
- res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
+ res = vfat_find(dir,&dentry->d_name,0,0,&sinfo);
X
X if (res >= 0 && sinfo.total_slots > 0) {
- res = vfat_remove_entry(dir,&sinfo,&bh,dentry,0,nospc);
+ if (!S_ISREG(dentry->d_inode->i_mode) && nospc) {
+ return -EPERM;
+ }
+ res = vfat_remove_entry(dir,&sinfo,dentry->d_inode);
X if (res > 0) {
X res = 0;
X }
X }
X
- if (bh) fat_brelse(sb, bh);
X return res;
X }
X
@@ -1586,6 +1491,7 @@
X int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
X {
X struct inode *inode;
+ struct vfat_slot_info sinfo;
X int res;
X
X PRINTK1(("vfat_mkdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
@@ -1597,17 +1503,28 @@
X
X dir->i_nlink++;
X inode->i_nlink = 2; /* no need to mark them dirty */
- MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
X
X res = vfat_create_dotdirs(inode, dir);
+ if (res < 0)
+ goto mkdir_failed;
X fat_unlock_creation();
- MSDOS_I(inode)->i_busy = 0;
X dentry->d_time = dentry->d_parent->d_inode->i_version;
X d_instantiate(dentry,inode);
- if (res < 0) {
- if (vfat_rmdir(dir,dentry) < 0)
- fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
- }
+ return res;
+
+mkdir_failed:
+ fat_unlock_creation();
+ if (vfat_find(dir,&dentry->d_name,0,0,&sinfo) < 0)
+ goto mkdir_panic;
+ if (vfat_remove_entry(dir, &sinfo, inode) < 0)
+ goto mkdir_panic;
+ iput(inode);
+ dir->i_nlink--;
+ return res;
+
+mkdir_panic:
+ dir->i_version = ++event;
+ fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
X return res;
X }
X
@@ -1619,7 +1536,7 @@
X PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
X res = vfat_unlinkx (dir,dentry,1);
X if (res >= 0) {
- drop_replace_inodes(dentry, NULL);
+ drop_aliases(dentry);
X d_delete(dentry);
X }
X return res;
@@ -1640,7 +1557,7 @@
X {
X struct super_block *sb = old_dir->i_sb;
X struct buffer_head *old_bh,*new_bh,*dotdot_bh;
- struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
+ struct msdos_dir_entry *old_de,*dotdot_de;
X loff_t old_offset,new_offset,old_longname_offset;
X int old_slots,old_ino,new_ino,dotdot_ino;
X struct inode *old_inode, *new_inode, *dotdot_inode;
@@ -1648,21 +1565,23 @@
X int res, is_dir, i;
X int locked = 0;
X struct vfat_slot_info sinfo;
- int put_new_inode = 0;
X
X PRINTK1(("vfat_rename: Entering: old_dentry=%p, old_inode=%p, old ino=%ld, new_dentry=%p, new_inode=%p, new ino=%ld\n",
X old_dentry, old_dentry->d_inode, old_dentry->d_inode->i_ino,
X new_dentry, new_dentry->d_inode,
X new_dentry->d_inode ? new_dentry->d_inode->i_ino : 0));
- if (old_dir == new_dir &&
- old_dentry->d_name.len == new_dentry->d_name.len &&
- strncmp(old_dentry->d_name.name, new_dentry->d_name.name,
- old_dentry->d_name.len) == 0)
+ /*
+ * POSIX is braindead (surprise, surprise). It requires that rename()
+ * should return 0 and do nothing if the target has the same inode as
+ * the source. Somebody, get a time machine, return to '89 and tell
+ * RMS & Co *not* to do that idiocy, FAST!
+ */
+ if (old_dentry->d_inode == new_dentry->d_inode)
X return 0;
X
X old_bh = new_bh = NULL;
X old_inode = new_inode = NULL;
- res = vfat_find(old_dir,&old_dentry->d_name,1,0,0,&sinfo);
+ res = vfat_find(old_dir,&old_dentry->d_name,0,0,&sinfo);
X PRINTK3(("vfat_rename 2\n"));
X if (res < 0) goto rename_done;
X
@@ -1677,90 +1596,102 @@
X res = -ENOENT;
X old_inode = old_dentry->d_inode;
X is_dir = S_ISDIR(old_inode->i_mode);
+
+ /*
+ * Race: we can be hit by another rename after this check.
+ * For the time being use fat_lock_creation(), but it's
+ * ugly. FIXME.
+ */
+
+ fat_lock_creation(); locked = 1;
+
X if (is_dir) {
- if ((old_dir->i_dev != new_dir->i_dev) ||
- (old_ino == new_dir->i_ino)) {
+ /* We can't use d_subdir() here. Arrgh. */
+ for (walk=new_dentry;walk!=walk->d_parent;walk=walk->d_parent) {
+ if (walk->d_inode != old_dentry->d_inode)
+ continue;
X res = -EINVAL;
X goto rename_done;
X }
- walk = new_dentry;
- /* prevent moving directory below itself */
- for (;;) {
- if (walk == old_dentry) return -EINVAL;
- if (walk == walk->d_parent) break;
- walk = walk->d_parent;
- }
X }
X
- res = vfat_find(new_dir,&new_dentry->d_name,1,0,is_dir,&sinfo);
-
- PRINTK3(("vfat_rename 4\n"));
- if (res > -1) {
- int new_is_dir;
-
- PRINTK3(("vfat_rename 5\n"));
- /* Filename currently exists. Need to delete it */
- new_offset = sinfo.shortname_offset;
- res = fat_get_entry(new_dir, &new_offset, &new_bh, &new_de);
- PRINTK3(("vfat_rename 6\n"));
- if (res < 0) goto rename_done;
+ if (new_dentry->d_inode) {
+ /*
+ * OK, we have to remove the target. We should do it so
+ * that nobody might go and find it negative. Actually we
+ * should give warranties wrt preserving target over the
+ * possible crash, but that's another story. We can't
+ * get here with the target unhashed, so the directory entry
+ * must exist.
+ */
X
- if (!(new_inode = iget(new_dir->i_sb,res)))
+ new_inode = new_dentry->d_inode;
+ res = vfat_find(new_dir,&new_dentry->d_name,0,is_dir,&sinfo);
+ if (res < 0 || new_inode->i_ino != sinfo.ino) {
+ /* WTF??? Cry and fail. */
+ printk(KERN_WARNING "vfat_rename: fs corrupted\n");
X goto rename_done;
- new_is_dir = S_ISDIR(new_inode->i_mode);
- iput(new_inode);
- if (new_is_dir) {
- PRINTK3(("vfat_rename 7\n"));
- res = vfat_rmdirx(new_dir,new_dentry);
- PRINTK3(("vfat_rename 8\n"));
- if (res < 0) goto rename_done;
- } else {
- /* Is this the same file, different case? */
- if (new_inode != old_inode) {
- PRINTK3(("vfat_rename 9\n"));
- res = vfat_unlink(new_dir,new_dentry);
- PRINTK3(("vfat_rename 10\n"));
- if (res < 0) goto rename_done;
+ }
+
+ if (is_dir) {
+ /*
+ * Target is a directory. No other owners will
+ * be tolerated.
+ */
+ res = -EBUSY;
+ if (d_invalidate(new_dentry) < 0)
+ goto rename_done;
+ /*
+ * OK, let's try to get rid of other dentries.
+ * No need to do it if i_count is 1.
+ */
+ if (new_inode->i_count>1) {
+ shrink_dcache_parent(new_dentry->d_parent);
+ if (new_inode->i_count>1)
+ goto rename_done;
X }
+ res = vfat_empty(new_inode);
+ if (res)
+ goto rename_done;
+ } else {
+ drop_aliases(new_dentry);
X }
X }
+ res = vfat_remove_entry(new_dir,&sinfo,new_inode);
+ if (res)
+ goto rename_done;
+
+ /* Serious lossage here. FAT uses braindead inode numbers scheme,
+ * so we can't simply cannibalize the entry. It means that we have
+ * no warranties that crash here will not make target disappear
+ * after reboot. Lose, lose. Nothing to do with that until we'll
+ * separate the functions of i_ino: it serves both as a search key
+ * in icache and as a part of stat output. It would kill all the
+ * 'busy' stuff on the spot. Later.
+ */
X
- PRINTK3(("vfat_rename 11\n"));
- fat_lock_creation(); locked = 1;
- res = vfat_find(new_dir,&new_dentry->d_name,1,1,is_dir,&sinfo);
+ if (is_dir)
+ new_dir->i_nlink--;
+
+ res = vfat_find(new_dir,&new_dentry->d_name,1,is_dir,&sinfo);
X
- PRINTK3(("vfat_rename 12\n"));
X if (res < 0) goto rename_done;
X
X new_offset = sinfo.shortname_offset;
X new_ino = sinfo.ino;
- PRINTK3(("vfat_rename 13: new_ino=%d\n", new_ino));
-
- if (!(new_inode = iget(new_dir->i_sb,new_ino))) goto rename_done;
- put_new_inode = 1;
X
- new_inode->i_mode = old_inode->i_mode;
- new_inode->i_size = old_inode->i_size;
- new_inode->i_blocks = old_inode->i_blocks;
- new_inode->i_mtime = old_inode->i_mtime;
- new_inode->i_atime = old_inode->i_atime;
- new_inode->i_ctime = old_inode->i_ctime;
- new_inode->i_nlink = old_inode->i_nlink;
- new_inode->i_op = old_inode->i_op;
- MSDOS_I(new_inode)->i_ctime_ms = MSDOS_I(old_inode)->i_ctime_ms;
-
- MSDOS_I(new_inode)->i_start = MSDOS_I(old_inode)->i_start;
- MSDOS_I(new_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart;
- MSDOS_I(new_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs;
+ /* XXX: take care of other owners */
X
+ remove_inode_hash(old_inode);
X fat_cache_inval_inode(old_inode);
- mark_inode_dirty(new_inode);
+ old_inode->i_ino = new_ino;
+ old_inode->i_version = ++event;
+ insert_inode_hash(old_inode);
+ mark_inode_dirty(old_inode);
X
X old_dir->i_version = ++event;
X new_dir->i_version = ++event;
X
- PRINTK3(("vfat_rename 14: old_slots=%d\n",old_slots));
-
X /* remove the old entry */
X for (i = old_slots; i > 0; --i) {
X res = fat_get_entry(old_dir, &old_longname_offset, &old_bh, &old_de);
@@ -1772,9 +1703,8 @@
X old_de->attr = 0;
X fat_mark_buffer_dirty(sb, old_bh, 1);
X }
- PRINTK3(("vfat_rename 15b\n"));
X
- if (S_ISDIR(old_inode->i_mode)) {
+ if (is_dir) {
X if ((res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
X &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
X if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
@@ -1796,26 +1726,11 @@
X fat_brelse(sb, dotdot_bh);
X }
X
- /*
- * This convinces the VFS layer to drop the old inode,
- * but at the same time fools the VFAT layer to not
- * actually delete any of the blocks in the old file
- * (because they are very much used by the renamed file)
- */
- MSDOS_I(old_inode)->i_start = 0;
- MSDOS_I(old_inode)->i_logstart = 0;
- old_inode->i_nlink = 0;
-
- if (res > 0) res = 0;
-
- if (res == 0) {
- drop_replace_inodes(old_dentry, new_inode);
- list_del(&old_dentry->d_alias);
- iput(old_dentry->d_inode);
- d_instantiate(old_dentry, new_inode);
-
+ if (res >= 0) {
+ if (new_inode && is_dir)
+ d_rehash(new_dentry);
X d_move(old_dentry, new_dentry);
- put_new_inode = 0;
+ res = 0;
X }
X
X rename_done:
@@ -1825,9 +1740,8 @@
X fat_brelse(sb, old_bh);
X if (new_bh)
X fat_brelse(sb, new_bh);
- if (put_new_inode)
- iput(new_inode);
X return res;
+
X }
X
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v2.2.0-pre7/linux/include/asm-alpha/processor.h Fri Oct 23 22:01:22 1998
+++ linux/include/asm-alpha/processor.h Mon Jan 18 09:55:30 1999
@@ -65,7 +65,7 @@
X };
X
X #define INIT_MMAP { &init_mm, PAGE_OFFSET, PAGE_OFFSET+0x10000000, \
- PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
+ NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
X
X #define INIT_TSS { \
X 0, 0, 0, \
@@ -113,6 +113,7 @@


X
X #define copy_segments(nr, tsk, mm) do { } while (0)
X #define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
X

X /* NOTE: The task struct and the stack go together! */
X #define alloc_task_struct() \
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.2.0-pre7/linux/include/asm-alpha/semaphore.h Tue May 13 22:41:15 1997
+++ linux/include/asm-alpha/semaphore.h Sat Jan 16 17:02:51 1999
@@ -7,28 +7,80 @@
X * (C) Copyright 1996 Linus Torvalds
X */
X
+#include <asm/current.h>
+#include <asm/system.h>
X #include <asm/atomic.h>
X
+/*
+ * Semaphores are recursive: we allow the holder process to recursively do
+ * down() operations on a semaphore that the process already owns. In order
+ * to do that, we need to keep a semaphore-local copy of the owner and the


+ * "depth of ownership".
+ *
+ * NOTE! Nasty memory ordering rules:

+ * - "owner" and "owner_count" may only be modified once you hold the lock.
+ * - "owner_count" must be written _after_ modifying owner, and must be
+ * read _before_ reading owner. There must be appropriate write and read
+ * barriers to enforce this.
+ */
+


X struct semaphore {
X atomic_t count;

X atomic_t waking;
+ struct task_struct *owner;
+ long owner_depth;


X struct wait_queue * wait;
X };
X

-#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
-#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
+#define MUTEX ((struct semaphore) \
+ { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL, 0, NULL })
+#define MUTEX_LOCKED ((struct semaphore) \
+ { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL, 1, NULL })
+
+#define semaphore_owner(sem) ((sem)->owner)
+#define sema_init(sem, val) atomic_set(&((sem)->count), val)
X
X extern void __down(struct semaphore * sem);
X extern int __down_interruptible(struct semaphore * sem);
X extern void __up(struct semaphore * sem);
X
-#define sema_init(sem, val) atomic_set(&((sem)->count), val)
+/* All three have custom assembly linkages. */
+extern void __down_failed(struct semaphore * sem);
+extern void __down_failed_interruptible(struct semaphore * sem);
+extern void __up_wakeup(struct semaphore * sem);
+
X
X /*
X * These two _must_ execute atomically wrt each other.
X *
X * This is trivially done with load_locked/store_cond,
X * which we have. Let the rest of the losers suck eggs.
+ *
+ * Tricky bits --
+ *
+ * (1) One task does two downs, no other contention
+ * initial state:
+ * count = 1, waking = 0, depth = undef;
+ * down(&sem)
+ * count = 0, waking = 0, depth = 1;
+ * down(&sem)
+ * atomic dec and test sends us to waking_non_zero via __down
+ * count = -1, waking = 0;
+ * conditional atomic dec on waking discovers no free slots
+ * count = -1, waking = 0;
+ * test for owner succeeeds and we return ok.
+ * count = -1, waking = 0, depth = 2;
+ * up(&sem)
+ * dec depth
+ * count = -1, waking = 0, depth = 0;
+ * atomic inc and test sends us to slow path
+ * count = 0, waking = 0, depth = 0;
+ * notice !(depth < 0) and don't call __up.
+ * up(&sem)
+ * dec depth
+ * count = 0, waking = 0, depth = -1;
+ * atomic inc and test succeeds.
+ * count = 1, waking = 0, depth = 0;
X */
X
X static inline void wake_one_more(struct semaphore * sem)
@@ -36,48 +88,153 @@


X atomic_inc(&sem->waking);
X }
X
-static inline int waking_non_zero(struct semaphore *sem)
+static inline int waking_non_zero(struct semaphore *sem,

+ struct task_struct *tsk)
X {
+ long owner_depth;


X int ret, tmp;
X

+ owner_depth = sem->owner_depth;
+
+ /* Atomic decrement, iff the value is > 0. */
X __asm__ __volatile__(
X "1: ldl_l %1,%2\n"
X " ble %1,2f\n"
X " subl %1,1,%0\n"
X " stl_c %0,%2\n"
X " beq %0,3f\n"
- "2:\n"
+ "2: mb\n"
X ".section .text2,\"ax\"\n"
X "3: br 1b\n"
X ".previous"
X : "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
X : "0"(0));
X
+ ret |= ((owner_depth != 0) & (sem->owner == tsk));
+ if (ret) {
+ sem->owner = tsk;
+ wmb();
+ /* Don't use the old value, which is stale in the
+ !owner case. */
+ sem->owner_depth++;
+ }
+


X return ret;
X }
X

X /*
- * This isn't quite as clever as the x86 side, but the gp register
- * makes things a bit more complicated on the alpha..
+ * Whee. Hidden out of line code is fun. The contention cases are
+ * handled out of line in kernel/sched.c; arch/alpha/lib/semaphore.S
+ * takes care of making sure we can call it without clobbering regs.
X */
+
X extern inline void down(struct semaphore * sem)
X {
- if (atomic_dec_return(&sem->count) < 0)
- __down(sem);
+ /* Given that we have to use particular hard registers to
+ communicate with __down_failed anyway, reuse them in
+ the atomic operation as well.
+
+ __down_failed takes the semaphore address in $24, and
+ it's return address in $28. The pv is loaded as usual.
+ The gp is clobbered (in the module case) as usual. */
+
+ __asm__ __volatile__ (
+ "/* semaphore down operation */\n"
+ "1: ldl_l $27,%3\n"
+ " subl $27,1,$27\n"
+ " mov $27,$28\n"
+ " stl_c $28,%0\n"
+ " beq $28,2f\n"
+ " blt $27,3f\n"
+ /* Got the semaphore no contention. Set owner and depth. */
+ " stq $8,%1\n"
+ " lda $28,1\n"
+ " wmb\n"
+ " stq $28,%2\n"
+ "4: mb\n"
+ ".section .text2,\"ax\"\n"
+ "2: br 1b\n"
+ "3: lda $24,%3\n"
+ " jsr $28,__down_failed\n"
+ " ldgp $29,0($28)\n"
+ " br 4b\n"
+ ".previous"
+ : "=m"(sem->count), "=m"(sem->owner), "=m"(sem->owner_depth)
+ : "m"(sem->count)
+ : "$24", "$27", "$28", "memory");
X }
X
X extern inline int down_interruptible(struct semaphore * sem)
X {
- int ret = 0;
- if (atomic_dec_return(&sem->count) < 0)
- ret = __down_interruptible(sem);
+ /* __down_failed_interruptible takes the semaphore address in $24,
+ and it's return address in $28. The pv is loaded as usual.
+ The gp is clobbered (in the module case) as usual. The return
+ value is in $24. */
+
+ register int ret __asm__("$24");
+
+ __asm__ __volatile__ (
+ "/* semaphore down interruptible operation */\n"
+ "1: ldl_l $27,%4\n"
+ " subl $27,1,$27\n"
+ " mov $27,$28\n"
+ " stl_c $28,%1\n"
+ " beq $28,2f\n"
+ " blt $27,3f\n"
+ /* Got the semaphore no contention. Set owner and depth. */
+ " stq $8,%2\n"
+ " lda $28,1\n"
+ " wmb\n"
+ " stq $28,%3\n"
+ " mov $31,$24\n"
+ "4: mb\n"
+ ".section .text2,\"ax\"\n"
+ "2: br 1b\n"
+ "3: lda $24,%4\n"
+ " jsr $28,__down_failed_interruptible\n"
+ " ldgp $29,0($28)\n"
+ " br 4b\n"
+ ".previous"
+ : "=r"(ret), "=m"(sem->count), "=m"(sem->owner),
+ "=m"(sem->owner_depth)
+ : "m"(sem->count)
+ : "$27", "$28", "memory");
+


X return ret;
X }
X

X extern inline void up(struct semaphore * sem)
X {
- if (atomic_inc_return(&sem->count) <= 0)
- __up(sem);
-}
+ /* Given that we have to use particular hard registers to
+ communicate with __up_wakeup anyway, reuse them in
+ the atomic operation as well.
+
+ __up_wakeup takes the semaphore address in $24, and
+ it's return address in $28. The pv is loaded as usual.
+ The gp is clobbered (in the module case) as usual. */
+
+ __asm__ __volatile__ (
+ "/* semaphore up operation */\n"
+ " mb\n"
+ "1: ldl_l $27,%1\n"
+ " addl $27,1,$27\n"
+ " mov $27,$28\n"
+ " stl_c $28,%0\n"
+ " beq $28,2f\n"
+ " mb\n"
+ " ble $27,3f\n"
+ "4:\n"
+ ".section .text2,\"ax\"\n"
+ "2: br 1b\n"
+ "3: lda $24,%1\n"
+ " bge %2,4b\n"
+ " jsr $28,__up_wakeup\n"
+ " ldgp $29,0($28)\n"
+ " br 4b\n"
+ ".previous"
+ : "=m"(sem->count)
+ : "m"(sem->count), "r"(--sem->owner_depth)
+ : "$24", "$27", "$28", "memory");
+}
X
X #endif
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v2.2.0-pre7/linux/include/asm-alpha/system.h Thu Dec 31 10:29:02 1998
+++ linux/include/asm-alpha/system.h Sat Jan 16 17:02:51 1999
@@ -107,6 +107,9 @@
X #define mb() \
X __asm__ __volatile__("mb": : :"memory")
X
+#define rmb() \
+__asm__ __volatile__("mb": : :"memory")
+
X #define wmb() \
X __asm__ __volatile__("wmb": : :"memory")
X
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h
--- v2.2.0-pre7/linux/include/asm-arm/processor.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/processor.h Mon Jan 18 09:55:30 1999
@@ -53,11 +53,9 @@
X extern void release_thread(struct task_struct *);
X

X /* Copy and release all segment info associated with a VM */

-extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm);
-extern void release_segments(struct mm_struct * mm);
-


X #define copy_segments(nr, tsk, mm) do { } while (0)
X #define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
X

X #define init_task (init_task_union.task)
X #define init_stack (init_task_union.stack)
diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h
--- v2.2.0-pre7/linux/include/asm-arm/semaphore.h Fri Jan 8 22:36:23 1999
+++ linux/include/asm-arm/semaphore.h Thu Jan 14 15:53:25 1999
@@ -48,7 +48,7 @@
X restore_flags(flags);


X }
X
-static inline int waking_non_zero(struct semaphore *sem)
+static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
X {

X unsigned long flags;


X int ret = 0;

diff -u --recursive --new-file v2.2.0-pre7/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.2.0-pre7/linux/include/asm-i386/processor.h Fri Jan 1 12:58:21 1999
+++ linux/include/asm-i386/processor.h Mon Jan 18 17:33:46 1999
@@ -238,7 +238,7 @@
X };
X
X #define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
+{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }


SHAR_EOF
true || echo 'restore of patch-2.2.0-pre8 failed'
fi

echo 'End of part 15'
echo 'File patch-2.2.0-pre8 is continued in part 16'
echo 16 > _shar_seq_.tmp
exit 0

0 new messages